先来看一段代码
public class Test {
public String method1() {
String ret = "";
for(int i=0;i<100000;i++){
ret=ret+"ok";
}
return ret;
}
public String method2() {
StringBuilder ret = new StringBuilder("");
for(int i=0;i<100000;i++){
ret.append("ok");
}
return ret.toString();
}
}
都知道method1的性能会比method2的性能差。
那么理由是什么理由呢?
下面咱们来证明一下:
先编译代码,然后找到Test.class文件,然后执行命令
javap -verbose Test.class >tt.txt
然后打开tt.txt
public java.lang.String method1();
descriptor: ()Ljava/lang/String;
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=1
0: ldc #2 // String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: sipush 1000
9: if_icmpge 38 //for循环
12: new #3 创建一个StringBuilder对象// class java/lang/StringBuilder
15: dup
16: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
19: aload_1
20: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
23: ldc #6 // String ok
25: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore_1
32: iinc 2, 1
35: goto 5
38: aload_1
39: areturn
可以看出每次循环一次就new一个对象。
再来看看method2
public java.lang.String method2();
descriptor: ()Ljava/lang/String;
flags: ACC_PUBLIC
Code:
stack=3, locals=3, args_size=1
0: new #3 创建一个StringBuilder对象// class java/lang/StringBuilder
3: dup
4: ldc #2 // String
6: invokespecial #8 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
9: astore_1
10: iconst_0
11: istore_2
12: iload_2
13: sipush 1000
16: if_icmpge 32 //循环
19: aload_1
20: ldc #6 // String ok
22: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
25: pop
26: iinc 2, 1
29: goto 12
32: aload_1
33: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
36: areturn
LineNumberTable:
有上面看出method2值创建了一个StringBuilder对象。
method1要创建n多个对象,而method2只需要创建一个对象,明显method2方式效率更高,推荐使用method2(StringBuilder)方式。
但是如果在多线程环境下使用的话,推荐StringBuffer,因为StringBuffer是线程安全的。
StringBuffer为什么线程安全,还不就是在方法上加了一个synchronized修饰罢了。