如何在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
此行的堆栈上的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”将在行String str= str1+str2;
共享相同的内存String str= str1+str2;
但str1 + str2如何在常量字符串池中直接生成“string”。 不调用任何String Builder类,就像我不写final
。 ? 看看它是否与实习生有关
我写了这个片段
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. "":(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
字符串有什么特别之处,我绝对不知道吗?
http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28说
引用常量变量(第4.12.4节)的简单名称(第6.5.6.1节)是常量表达式。
http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28也说:
常量表达式是表示基本类型的值的表达式或不突然完成的字符串,仅使用以下内容组成:
- 原始类型的文字和String类型的文字(§3.10.1,§3.10.2,§3.10.3,§3.10.4,§3.10.5)
- […]
- 加法运算符+和 – (§15.18)
- […]
- 引用常量变量的简单名称(第6.5.6.1节)(§4.12.4)。
例15.28-1。 常数表达式
[…]
“整数”+ Long.MAX_VALUE +“非常大。”
由于这两个变量是常量表达式,编译器会进行连接:
String str = str1 + str2;
编译方式与。相同
String str = "str" + "ing";
这与编译方式相同
String str = "string";