这个东西说过的人太多了,其实也没有什么好再说的.我说的都是别人说过的.不过,别人说的始终是别人的,看过即忘,
java源码
package cn.jvm;
public class StringTest {
public static void main(String[] args) {
test1();
test2();
}
public static void test1() {
String a="single";
String b="dog";
String c=a+b;
System.out.println(c);
}
public static void test2() {
StringBuilder sb=new StringBuilder();
String a="single";
String b="dog";
sb.append(a);
sb.append(b);
String c=sb.toString();
System.out.println(c);
}
}
jVM字节码
public static void test1();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=3, args_size=0
0: ldc #24 // String single //将single从常量池中推送到栈顶
2: astore_0 //将栈顶数弹给变量0,a=single
3: ldc #26 // String dog
5: astore_1 //b=dog
6: new #28 // class java/lang/StringBuilder //new一个StringBuilder对象,并将其压入栈顶
9: dup //复制栈顶数值并将复制值压入栈
10: aload_0 //single入栈
11: invokestatic #30 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
14: invokespecial #36 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V //初始化StringBuilder对象
17: aload_1 //dog入栈
18: invokevirtual #39 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; //使用StringBuilder的append方法拼接字符串
21: invokevirtual #43 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; //StringBuilder转成String
24: astore_2 //将栈值弹给c c=singledog
25: getstatic #47 // Field java/lang/System.out:Ljava/io/PrintStream;
28: aload_2
29: invokevirtual #53 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
32: return
LineNumberTable:
line 10: 0
line 11: 3
line 12: 6
line 13: 25
line 14: 32
LocalVariableTable:
Start Length Slot Name Signature
3 30 0 a Ljava/lang/String;
6 27 1 b Ljava/lang/String;
25 8 2 c Ljava/lang/String;
public static void test2();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=0
0: new #28 // class java/lang/StringBuilder //创建StringBuilder对象,并将其压入栈顶
3: dup //复制栈顶数值并将复制值压入栈
4: invokespecial #62 // Method java/lang/StringBuilder."<init>":()V//初始化StringBuilder对象
7: astore_0 //sb=new StringBuilder()
8: ldc #24 // String single
10: astore_1 //a=single
11: ldc #26 // String dog
13: astore_2 //b=dog;
14: aload_0 //sb对象入栈
15: aload_1 //single入栈
16: invokevirtual #39 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; //sb.append(single)
19: pop //从栈顶弹出
20: aload_0
21: aload_2
22: invokevirtual #39 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;sb.append(dog)
25: pop
26: aload_0
27: invokevirtual #43 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; sb.toString
30: astore_3 //c=sb.toString
31: getstatic #47 // Field java/lang/System.out:Ljava/io/PrintStream;
34: aload_3
35: invokevirtual #53 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: return
LineNumberTable:
line 17: 0
line 18: 8
line 19: 11
line 20: 14
line 21: 20
line 22: 26
line 23: 31
line 24: 38
LocalVariableTable:
Start Length Slot Name Signature
8 31 0 sb Ljava/lang/StringBuilder;
11 28 1 a Ljava/lang/String;
14 25 2 b Ljava/lang/String;
31 8 3 c Ljava/lang/String;
}
从这个例子来看,a+b的底层,其实也是使用了StringBuilder的append()方法,由此来看,似乎两者差别不大.
java源码
package cn.jvm;
public class StringTest3 {
public static void main(String[] args) {
test1();
test2();
}
public static void test1() {
String a="work";
String b="";
for(int i=0;i<10;i++) {
b+=a;
}
System.out.println(b);
}
public static void test2() {
String a="work";
StringBuilder sb=new StringBuilder();
for(int i=0;i<10;i++) {
sb.append(a);
}
String b=sb.toString();
System.out.println(b);
}
}
JVM字节码
public static void test1();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=3, args_size=0
0: ldc #24 // String work
2: astore_0 //a=work;
3: ldc #26 // String
5: astore_1 //b="";
6: iconst_0
7: istore_2 //i=1
8: goto 33 //去到第33 i入栈
-------------------循环开始-------------------
11: new #28 // class java/lang/StringBuilder //创建一个StringBuilder,这是在循环内创建
14: dup
15: aload_1
16: invokestatic #30 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
19: invokespecial #36 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
22: aload_0
23: invokevirtual #39 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
26: invokevirtual #43 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
29: astore_1
30: iinc 2, 1
33: iload_2 //i入栈
34: bipush 10 //10入栈
36: if_icmplt 11 //如果i<10,去到第11
/----------循环结束--------------------
39: getstatic #47 // Field java/lang/System.out:Ljava/io/PrintStream;
42: aload_1
43: invokevirtual #53 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
46: return
public static void test2();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=0
0: ldc #24 // String work
2: astore_0 //a=work
3: new #28 // class java/lang/StringBuilder //创建一个StringBuilder,循环外创建
6: dup
7: invokespecial #64 // Method java/lang/StringBuilder."<init>":()V
10: astore_1 //sb=new StringBuilder()
11: iconst_0
12: istore_2 //i=0;
13: goto 25 //调到第25
/--------------------------循环开始-----------------
16: aload_1 //sb入栈
17: aload_0 //a入栈
18: invokevirtual #39 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: pop
22: iinc 2, 1
25: iload_2 //i入栈
26: bipush 10 //10入栈
28: if_icmplt 16 //如果i<10,调到第16
//-----------------循环结束-------------------
31: aload_1
32: invokevirtual #43 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
35: astore_2
36: getstatic #47 // Field java/lang/System.out:Ljava/io/PrintStream;
39: aload_2
40: invokevirtual #53 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
43: return
从上面的字节码中可以明显的看到,在test1()中,每次循环都会新建一个StringBuilder对象,而在test2中,只有一个StringBuilder对象.
版权声明:本文为bushanyantanzhe原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。