最终字符串的串联是如何在Java中完成的?
当我编译这个片段时。
public class InternTest {
public static void main(String...strings ){
final String str1="str";
final String str2="ing";
String str= str1+str2;
}
}
生成以下字节码
public static void main(java.lang.String...);
flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
Code:
stack=1, locals=4, args_size=1
0: ldc #16 // String str
2: astore_1
3: ldc #18 // String ing
5: astore_2
6: ldc #20 // String string
8: astore_3
9: return
所以字符串文字“字符串”已经存在于常量池中,该池在此行被推到堆栈上。6: ldc #20 // String string
引用 JSL
来自 JLS §4.12.4 - 最终变量:
基元类型或 String 类型的变量称为常量变量,它是 final 并使用编译时常量表达式 (§15.28) 初始化。
同样来自 JLS §15.28 - ConstantExpression:
String 类型的编译时常量表达式始终是“暂存的”,以便使用方法 String#intern() 共享唯一的实例。
所以我知道 str1 和 str2 将在创建的那一刻就被拘留。str“和”ing“将在第一行共享相同的内存,但是str1 + str2如何在常量字符串池中直接生成”字符串”。无需调用任何字符串生成器类,就像我不写 final
时所做的那样。?看看它是否与实习生的事情有关String str= str1+str2;
我写了这个片段
public class IntermTest {
public static void main(String...strings ){
String str1=("str").intern();
String str2=("ing").intern();
String str= str1+str2;
}
}
但是当我生成字节码时,我得到了这个
public static void main(java.lang.String...);
flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
Code:
stack=3, locals=4, args_size=1
0: ldc #16 // String str
2: invokevirtual #18 // Method java/lang/String.intern:
()Ljava/lang/String;
5: astore_1
6: ldc #24 // String ing
8: invokevirtual #18 // Method java/lang/String.intern:
()Ljava/lang/String;
11: astore_2
12: new #26 // class java/lang/StringBuilder
15: dup
16: aload_1
17: invokestatic #28 // Method java/lang/String.valueOf
:(Ljava/lang/Object;)Ljava/lang/String;
20: invokespecial #32 // Method java/lang/StringBuilder.
"<init>":(Ljava/lang/String;)V
23: aload_2
24: invokevirtual #35 // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
27: invokevirtual #39 // Method java/lang/StringBuilder.
toString:()Ljava/lang/String;
30: astore_3
31: return
实际上,它也用于串联。所以它对最终做了一些事情。字符串有什么特别之处,我绝对不知道吗?stringBuilder
final