如何在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";