Java 7 - String.intern()的行为

4

我已经阅读了关于如何在Java中检查字符串是否被intern的答案,但是我不理解以下结果:

String x = args[0]; // args[0] = "abc";
String a = "a";
String y = a + "bc";
System.out.println(y.intern() == y); // true

但是如果我声明一个字符串字面量:

String x = "abc";
String a = "a";
String y = a + "bc";
System.out.println(y.intern() == y); // false

此外,如果没有任何字符串文字,args [0] 似乎会直接进行内部化:
// String x = "abc";
String y = args[0];
System.out.println(y.intern() == y); // true (???)
// false if the first line is uncommented

为什么y.intern() == y的结果会因x是字面量还是非字面量而改变,即使在使用命令行参数的示例中也是如此?
我知道字面量字符串在编译时被interned,但我不明白为什么它会影响前面的示例。我也阅读了一些关于字符串interning的问题,例如String Pool behaviorQuestions about Java's String poolJava String pool - When does the pool change?。然而,它们都没有给出这种行为的可能解释。 编辑: 我错误地写道,在第三个示例中,如果声明String x = "abc";,结果不会改变,但实际上会改变。

1
在所有情况下,我都得到了 false。 - aditsu quit because SE is EVIL
如果编译器“作弊”并结合第二个和第三个赋值(这在Java规则下最多是合法的),则第二种情况可能会得到“true”。 - Hot Licks
1
@HotLicks - 只有变量被声明为final时才能这样做。 - Perception
解释很简单:如果你得到的是true,那么这个字符串已经被内部化了,否则你会得到false。关于它,这就是所有可以说的了。对于“为什么xyz没有被interned()?”的答案是“因为没有人这样做。”而“为什么abc被interned?”的答案是“因为已经有人这样做了。” - Ingo
2
@MartijnCourteaux - 不知道你为什么说“可怕”。给定的字符串值可能已经被内部化,也可能在一个小时前在不同的方法中。此外,即使是第一个这样的字符串,intern()也不能保证返回原始字符串--它可能会返回一个副本。 - Hot Licks
显示剩余4条评论
2个回答

6

这是因为y.intern()会返回y,如果该字符串之前没有被内部化。如果该字符串已经存在,调用将返回已经存在的实例,该实例很可能与y不同。

然而,所有这些都高度依赖于具体实现,因此在不同版本的JVM和编译器上可能会有所不同。


那么这是否意味着当字符串已经被interned时,y.intern() == y是false的?这是否与我在开头提到的答案矛盾呢?(参考链接:https://dev59.com/vG445IYBdhLWcg3wZJYn#4883828) - A. Rodas
如果一个等于 y 但是不同实例的字符串已经被驻留,那么你会得到 false。如果与 y 相同的实例先前已被驻留,那么你将得到 true。如果之前没有被驻留任何等于 y 的字符串,也会返回 true。 - Henry
它确实与答案相矛盾,但是答案中的代码是错误的。应该使用“!=”来检查它是否已经被内部化。 - Jochen
@Jochen 这取决于答案是指 myString 实例还是仅等于 myString 的字符串。 - Henry
@Henry 确实。我猜这样一个看似简单的问题,如果没有一段较长的解释,是不可能用一行代码来回答的 :) - Jochen
@Henry,我做了一些测试,现在我更好地理解了。谢谢! - A. Rodas

0

实现细节可能有所不同。但这正是我所期望的行为。你的第一个情况意味着命令行参数默认情况下不会被内部化。因此,y.intern()在内部化后返回对y的引用。

第二种情况是虚拟机自动将文字串内部化,因此y.intern()返回对x的引用,这与y不同。

最后一种情况再次发生,因为默认情况下没有任何东西被内部化,因此调用intern()返回对y的引用。 我相信更积极地内部化字符串是合法的,但据我理解,这是规范所要求的最小行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接