先来看四个示例:
思考:
看着不太相同的程序, jvm在底层实现时是怎样的操作呢? 在程序运行过程中会创建几个对象呢?
示例1:
public static void main(String[] args) {
String str = "456";
String str2 = "abc"+"123"+str;
}
反编译结果:
Code:
stack=3, locals=3, args_size=1
0: ldc #16 // String 456
2: astore_1
3: new #18 // class java/lang/StringBuilder
6: dup
7: ldc #20 // String abc123
9: invokespecial #22 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
12: aload_1
13: invokevirtual #25 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: invokevirtual #29 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
19: astore_2
20: return
示例2:
public static void main(String[] args) {
String str = "456";
String str2 = "abc123"+str;
}
反编译结果:
Code:
stack=3, locals=3, args_size=1
0: ldc #16 // String 456
2: astore_1
3: new #18 // class java/lang/StringBuilder
6: dup
7: ldc #20 // String abc123
9: invokespecial #22 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
12: aload_1
13: invokevirtual #25 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: invokevirtual #29 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
19: astore_2
20: return
示例3:
public static void main(String[] args) {
String str = "abc123";
String str2 = "qwe456";
String str3 = str2+str;
}
反编译结果:
Code:
stack=3, locals=4, args_size=1
0: ldc #16 // String abc123
2: astore_1
3: ldc #18 // String qwe456
5: astore_2
6: new #20 // class java/lang/StringBuilder
9: dup
10: aload_2
11: invokestatic #22 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
14: invokespecial #28 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
17: aload_1
18: invokevirtual #31 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #35 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
24: astore_3
25: return
示例4:
public static void main(String[] args) {
String str = "abc"+"123"+"456";
}
反编译结果:
Code:
stack=1, locals=2, args_size=1
0: ldc #16 // String abc123456
2: astore_1
3: return
分析:
通过观察四个示例的反编译结果可以看到, 对于前三种程序, jvm底层的实现时完全一样;
- 对于"字符串常量 + 字符串变量" 和 “字符串变量 + 字符串变量” 这两种情况, jvm都是通过创建StringBuilder对象, 调用StringBuilder对象的append方法来实现" + "操作;
- 对于"字符串常量 + 字符串常量" , jvm是先去常量池里面找,如果在常量池中没有找到相对应的字符串, 才会去创建StringBuilder对象生成该字符串, 返回并放入常量池中