>>>写出下面程序运行结果:
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对象的。