String S1="He";
String S2="llow";
String S3="Hellow";
String S4="He"+"llow";
String S5=S1+S2;
System.out.println(S3==S4); // prints true
System.out.println(S5==S3); // prints false
System.out.println(S5==S4); // prints false
Run Code Online (Sandbox Code Playgroud)
为什么S5不从常量池中引用对象?因为S3并且S4在游泳池中这就是为什么给予真实S3==S4
但如果S5==S3&S5==S4结果为假,则意味着S5不在池中.
字符串s1通过s4都是编译时常量.
编译器"He" + "llow"在编译期间计算,并查询字符串池是否已经存在结果,如果不存在则将其放在那里.
但是计算s1 + s2不是在编译时完成的,因此其结果不会被实现.为什么?因为从理论上讲,另一个线程可以改变的值s1或者s2通过我们得到的这个代码指令的时间,因此,它可能设置s2到"foo",所以结果变成"Hefoo".
作为作者,您可能知道没有线程会这样做,而且无论如何这些都是局部变量,但编译器却没有.
如果您将定义更改为:
final String s1="He";
final String s2="llow";
final String s3="Hellow";
final String s4="He"+"llow";
final String s5=s1+s2;
Run Code Online (Sandbox Code Playgroud)
确实,结果s5 == s3将是true!为什么?因为final关键字让编译器知道这些字符串不会被替换,所以它们是这些变量的最终值.因此它可以在编译时计算它并获取池中已有的结果.