如何在Java中连接最终字符串?
当我编译这段代码时如何在Java中连接最终字符串?,java,string,final,Java,String,Final,当我编译这段代码时 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...); f
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和
使用编译时常量表达式(§15.28)初始化的
称为常量变量
同样来自JLS§15.28-恒久压力:
字符串类型的编译时常量表达式始终是“interned”
以便使用String#intern()方法共享唯一实例
所以我知道str1和str2在创建的那一刻就会被扣押。“str”和“ing”将在String str=str1+str2行共享相同的内存代码>
但是str1+str2如何在常量字符串池中直接生成“字符串”。没有像我不写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.
"<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
publicstaticvoidmain(java.lang.String…);
标志:ACC_PUBLIC、ACC_STATIC、ACC_VARARGS
代码:
堆栈=3,局部变量=4,参数大小=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//方法java/lang/String.valueOf
:(Ljava/lang/Object;)Ljava/lang/String;
20:invokespecial#32//方法java/lang/StringBuilder。
“”:(Ljava/lang/String;)V
23:aload_2
24:invokevirtual#35//方法java/lang/StringBuilder。
追加:(Ljava/lang/String;)Ljava/lang/StringBuilder;
27:invokevirtual#39//方法java/lang/StringBuilder。
toString:()Ljava/lang/String;
30:astore_3
31:返回
实际上,它还使用stringBuilder
进行连接。所以它和期末考试有关。final
字符串是否有我绝对不知道的特殊之处 说
引用常量变量(§4.12.4)的简单名称(§6.5.6.1)是常量表达式
还说:
常量表达式是表示原语类型的值或字符串的表达式,该值或字符串不会突然完成,并且仅使用以下内容组成:
- 基本类型的文字和字符串类型的文字(§3.10.1、§3.10.2、§3.10.3、§3.10.4、§3.10.5)
- [……]
- 加法运算符+和-(§15.18)
- [……]
- 引用常量变量(§4.12.4)的简单名称(§6.5.6.1)李>
例15.28-1。恒定表达式
[……]
整数“+Long.MAX_VALUE+”非常大
由于这两个变量是常量表达式,编译器将进行串联:
String str = str1 + str2;
编译方式与
String str = "str" + "ing";
String str = "string";
它的编译方式与
String str = "str" + "ing";
String str = "string";
如果编译器这样做,为什么它仍然隐藏在字节码中,或者它在其他地方这样做,因为如果我没有错,现代Java编译器会通过StringBuilder的append来转换我的+操作。
?正如我所说,连接是由编译器本身完成的,而不是在运行时完成的。为行String str=str1+str2
生成的字节码与为行String str=“String”
生成的字节码完全相同,因为str1+str2
是一个常量表达式。“因为str1+str2是一个常量表达式”或者更准确地说,因为str1和str2不仅仅是常数,但编译时常数允许编译器计算一次,并将结果放入代码中,而不是每次执行此代码时在运行时重新计算。有消息告诉我,这将是您下一个问题的答案:@Pshemo,当这变得清晰时..我认为这不会导致任何问题。。无论如何,谢谢你提出这么好的问题:)每个问题都是很棒的学习曲线!