当我编译这段代码时。
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
因此,字符串字面量"string"已经存在于常量池中,该常量池被推送到堆栈上的6: ldc #20 // String string
行。
JSL引用:
来自JLS §4.12.4 - final变量:
原始类型或String类型的变量,是final并使用编译时常量表达式(§15.28)进行初始化,则称为常量变量。
还来自JLS §15.28 -ConstantExpression:
类型为String的编译时常量表达式总是被“interned”以共享唯一实例,使用方法String#intern()。
所以我知道str1和str2只要创建就会被放入进常量池中。 "str"和"ing"将在String str = str1 + str2;
行共享内存。
final
那样调用任何String Builder类? 我不确定是否与intern有关,于是我写了这个代码片段。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
有些关系。关于final
字符串有什么特殊的地方我不知道吗?