事实上,这个问题是另一个问题的延续。
许多文章说,当您创建没有new
文字的字符串时,该字符串最终会出现在字符串池中。否则,需要一个方法intern
。那么如何解释下面的行为呢?
String s2 = "hello";
String s1 = "hello";
System.out.println(s1 == s2); // true
System.out.println("hel" + "lo" == "hello"); // true
s1 = "hello";
s2 = "hel";
String s3 = "lo";
System.out.println(s1 == s2 + s3); // false
System.out.println(s2 + s3 == "hel" + "lo"); //false
如果在后一种情况下它s2
指的是与文字“hel”相同的地方,并且具有s3
相同的故事,那么为什么"hel" + "lo"
它不等于(通过引用)s2 + s3
?
只有调用String类的intern方法后,字符串才会进入字符串池。
英文规范中有关字符串文字的详细信息
关于 "hel" + "lo" 是字符串常量
让我们上课
我们用反编译器编译看看
编译器将“hel”+“lo”编译成一行,为了证明,我们看一下字节码:
“hello”用常量表示,s2 + s3通过StringBuilder收集并通过toString()分别转换为字符串,这是2个不同的对象,比较指针的时候会为false
字符串可以在两种情况下进入常量池:
编译器遍历源代码中的所有行并将它们添加到常量池中。如果代码中有一些地方需要计算并且编译器可以执行它们,那么它就会执行。在您的示例中,这是
System.out.println("hel" + "lo" == "hello");
. 连接"hel" + "lo"
并放入池中。方法说明(文档链接)。这里有必要指定此方法的应用范围。这个方法看起来很诱人:“我们可以减少程序的内存使用和性能!!这是一个巨大的优化!!”
如果您不相信我,那么您应该相信Alexei Shipilev(约 32 分钟的实习生)。