>>>写出下面程序运行结果:
public class StringTest {public static void main(String[] args) {String s1 = "Programming";String a = "Program";String b = "ming";String s2 = "Program" + "ming";String s3 = a + b;System.out.println(s1 == s2);System.out.println(s1 == s3);System.out.println(s1 == s3.intern());}
}
>>>输出结果为:
true
false
true
>>>解析:
首先,intern()方法会将常量池中对应字符串的引用返回,如果常量池没有这个字符串,则将其添加到常量池,再返回常量池中的这个引用。所以第三个输出结果为true。
关于第一和第二个输出结果,可能迷惑性很大,这个我们需要借助于javap反编译工具来看一下编译过程:
执行 javap -c StringTest.class 命令,查看结果:
(如果图片看不清,可以点击图片查看原图)
图中画红框的两个部分,分别对应:
String s2 = "Program" + "ming";
String s3 = a + b;
可以看到,s2 通过字面量直接拼接的方式并没有创建StringBuilder对象,但是s3却创建了一个StringBuilder然后调用append()方法进行的字符串拼接。
因此,s2的地址在常量池中,s3的地址由于是new 了一个StringBuilder,因此是在堆(Heap)中,这才导致了 s1 == s3 的结果为 false。
所以,也并不是所有字符串拼接都是先创建一个StringBuilder对象的。这也会在面试题中经常被问到,即 “ 什么情况下用+运算符进行字符串连接比调用StringBuffer/StringBuilder对象的append方法连接字符串性能更好?”,就是在这种不会创建StringBuilder对象的情况下才会比append()性能好。