Java字符串intern和字面量

14

下面这两段代码是否相同?

String foo = "foo";
String foo = new String("foo").intern();
5个回答

16
它们有相同的“最终结果”,但它们并不相同(它们将生成不同的字节码;new String("foo").intern()版本实际上会执行这些步骤,生成一个新的字符串对象,然后将其放入字符串池中)。 String#intern 中的两个相关引用:
当调用 intern 方法时,如果池已经包含与该 String 对象相等的字符串(由 equals(Object) 方法确定),则返回池中的字符串。否则,将该 String 对象添加到池中,并返回对该 String 对象的引用。
所有文字字符串和字符串常量表达式都被纳入了池中。
因此,“最终结果”是相同的:一个变量引用了字符串池中的字符串“foo”。

在这种情况下,new String("foo").intern();,新创建的字符串对象没有被添加到堆中,对吗? - foo
3
@foo:可能是这样,但在表达式结束时,由于没有该对象的未解除引用,它立即可供垃圾回收机制再次回收。我预期优化的JVM(例如Sun/Oracle的HotSpot)会在第一次优化中消除new String("foo").intern(),一旦注意到调用构造函数没有副作用。或者不会消除,因为除非它在一个紧密循环内,否则它不符合值得优化的门槛。 - T.J. Crowder
谢谢。我在想为什么有人会使用new String("foo")这种方式来初始化字符串,因为如果我这样做,就会创建两个对象,一个在堆上,另一个在池中。除了在Java中初始化所有对象的统一模式外,使用new String("foo")是否有其他优点我没有注意到吗? - foo
1
@foo:我能想到的唯一好处是,如果你使用intern,即使字符串内容不同,你也知道字符串引用是唯一的。这样的用例不多,我认为不会有很多人需要,但由于按照定义new String("foo") != "foo",在某些情况下可能会派上用场。虽然这样的情况不多,我不认为会有很多。 - T.J. Crowder

4

public String intern()

因此,对于任意两个字符串s和t,如果且仅当s.equals(t)true时,s.intern() == t.intern()是真的。

所以我认为答案是肯定的,尽管第二种方法将不得不在池中搜索。

编辑

如T.J. Crowder所建议

当调用intern方法时,如果池中已经包含一个等于该String对象的字符串(根据equals(Object)方法确定),则返回池中的字符串。否则,将该String对象添加到池中,并返回对该String对象的引用。

所有文字字符串和值为字符串的常量表达式都被国际化。


1
我认为更相关的两个引用是:*"当调用intern方法时,如果池中已经包含一个与此String对象相等的字符串(由equals(Object)方法确定),则从池中返回该字符串。否则,将该String对象添加到池中,并返回对该String对象的引用。"* 和 "所有文字字符串和字符串值常量表达式都会进行内部化。" - T.J. Crowder
现在这应该是基于每个JVM的,对吧?所以如果我有一个集群,它会表现得不同。 - Pushkar

3

第一个,即

    String foo = "foo";

在这行代码中,我们使用字符串字面量创建了一个字符串。这意味着该字符串会自动保存在字符串常量池中。
第二个例子是 -
    String foo = new String("foo").intern();

在这里,我们使用new String()创建一个字符串,然后手动保存到字符串常量池中。如果我们没有使用intern(),它就不会保存在字符串常量池中。

为了更好的理解,请参考此链接 -

http://javacodingtutorial.blogspot.com/2013/12/comparing-string-objects-intern-other.html


2
这个答案完全错误。说第二段代码没有调用intern()就不会在字符串池中有String显然是错误的,因为它仍然使用字面量"foo"。在这种情况下,intern的效果是,对String构造函数的调用不再重要,而foo指的是字面版本"foo"而不是新构造的版本。 - Tom

0

是的,它们是相同的。基本上,intern() 返回一个在 VM 中唯一的字符串表示形式。这意味着您可以使用==而不是.equals()来比较字符串,从而节省性能。


0

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