4

可能重复:
我们什么时候应该使用String的intern方法?
什么是字符串实习?

请解释以下代码的内部工作原理:

System.out.println(new String("ABC").intern()==new String("ABC").intern());

在上面的代码中,它打印“true”。但是根据java规则,在new操作符的情况下,它总是会创建一个新对象。 object.intern()方法还在字符串池中创建一个对象。所以我的问题是,在上面的代码中创建了多少对象。

据我说,将创建 3 个新对象。一个进入字符串池,两个匿名对象将由 new 运算符创建。但我不确定。

如果我错了,请解释。

4

3 回答 3

1

假设优化器不聪明,创建了两个对象。(足够聪明的优化器可以将其优化为无条件的true,在这种情况下不会创建任何对象。)

tl;dr 版本:您对 3 的回答几乎是正确的,只是进入字符串池的字符串不是作为该语句的一部分生成的;它已经创建好了。

首先,让我们把"ABC"字面意思去掉。它在运行时表示为一个String对象,但它存在于 pergen 中并且在 JVM 的整个生命周期中被创建一次。如果这是第一个使用该字符串文字的类,则它是在类加载时创建的(请参阅JLS 12.5,其中指出 String 是在加载类时创建的,除非它以前存在)。

因此,第一个new String("ABC")创建 one String,它只是将引用(但不创建新对象)复制"ABC"到 chars 数组并从表示文字的 String 散列(同样,它不是作为该行的一部分创建的)。然后该.intern()方法查看是否已在 permgen 中存在相等的字符串。它是(它只是表示以文字开头的字符串),所以这就是该函数返回的内容。所以,new String("ABC").intern() == "ABC"。请参阅JLS 3.10.5,特别是:

此外,字符串字面量总是引用 String 类的同一个实例。这是因为字符串字面量 - 或者更一般地说,作为常量表达式值的字符串(第 15.28 节) - 是“内部的”,以便使用 String.intern 方法共享唯一实例。

同样的事情发生在第二次出现new String("ABC").intern(). 而且,由于这两种intern()方法都返回与文字相同的对象"ABC",因此它们表示相同的值。

稍微分解一下:

String a = new String("ABC"); // a != "ABC"
String aInterned = a.intern(); // aInterned == "ABC"

String b = new String("ABC"); // b != "ABC"
String bInterned = b.intern(); // bInterned == "ABC"

System.out.println(new String("ABC").intern()==new String("ABC").intern());
                                            // ... is equivalent to... 
System.out.println(aInterned == bInterned); // ...which is equivalent to...
System.out.println("ABC" == "ABC");         // ...which is always true.
于 2013-01-18T07:11:38.333 回答
0

当您调用intern()方法时,jvm 将检查给定的字符串是否存在,是否在字符串池中。如果它在那里,它将返回对它的引用,否则它将在池中创建一个新字符串并返回对它的引用。在你的情况下:System.out.println(new String("ABC").intern()==new String("ABC").intern());

第一个new String("ABC").intern()将在池中创建一个字符串“ABC”。当您new String("ABC").intern()第二次调用时,jvm 将返回对先前创建的字符串的引用。这就是您true在比较两者时得到的原因(btn 指向相同的引用)。

于 2013-01-18T06:02:32.370 回答
0

我相信你是对的,因为new操作创建了一个新对象,所以有 2 个匿名对象,并且intern()只有在它还没有的情况下才在字符串池中创建一个新字符串并返回它的引用

于 2013-01-18T06:29:27.347 回答