string常量池

正如在这些Stackoverflow的问题所解释的: 问题1和问题2我明白,“ string文字 ”是interned在下列情况下:

String s = "abc"; 

而且,当以下情况时,JVM将创build一个新的String对象,而不是使用string池中现有的对象:

 String s = new String("abc"); 

但是,在阅读以下两个类似的陈述之后,我有一个疑问。

  • 从SCJP准备书 :

当编译器遇到一个string时,它会检查这个池是否存在一个相同的string。 如果find匹配项,则对新文字的引用将定向到现有的string,并且不会创build新的string字面值对象。

  • 从JavaRanch:

在这种情况下,由于关键字“new”,我们实际上最终会有一个稍微不同的行为。 在这种情况下,对string文字的引用仍然放在常量表(string文字池)中,但是,当您使用关键字“new”时,JVM有义务在运行时创build一个新的String对象,而不是使用常量表中的一个。

所以如果我们在非池内存AND池内存中使用“new”创build一个对象,并且基于上面的定义,我们也会引用它。 当我们这样做时,JVM是否也应该返回相同的参考?

 String one = new String("test"); String two = "test"; System.out.println(one.equals(two)); // true System.out.println(one == two); // false 

因为在声明string时, String three = "test"; 它将已经存在于游泳池? 因此应该返回相同的参考和打印真实? 或者做以前的陈述意味着他们将被放入池内存中,但是当使用new操作符时,只是简单地跳过?

也许这将有助于你的理解:

 String literal = "test"; String one = new String(literal); String two = "test"; System.out.println(literal == two); //true System.out.println(one == two); //false 

在你发布的例子中:

 String one = new String("test"); String two = "test"; 

传递给构造函数String(String)的引用由于interning而具有与引用two相同的值。 然而,string本身(由这两个引用引用)用于构造一个新的对象,该对象被分配给引用one

在这个例子中,只有两个String是用“test”值创build的:当在expression式中使用文字"test"时候,在常量池中维护的String ,以及由“new”运算符创build的第二个String并分配给参考one

编辑

也许你对这个说法感到困惑:

当编译器遇到一个string时,它会检查这个池是否存在一个相同的string。

请注意,这可能更清楚地陈述为:

当编译器遇到String文字时,它会检查池中是否存在相同的string。

只有当string被显式实现时,才会将string放入池中,或者由类使用字面值。 所以,如果你有,例如,这种情况:

 String te = "te"; String st = "st"; String test = new String(te) + new String(st); 

那么当一个String与值test 存在时,string将不会存在于池中,因为字面"test"从来没有发生过。

  //Creates a new object even if one exists in the pool String s1 = new String("Tendulkar"); // makes a new object string and then the reference is available to the pool String s2 = s1.intern(); //this object is not created but references the address present in the pool String s3 = "Tendulkar"; System.out.print(s1==s2); // results in false System.out.print(s2==s3); //very very true !!! 

"abc" 在编译/类加载时将一个对象放入常量池中,而new String() 在执行时创build一个新对象 所以new String("abc")都做,但在不同的阶段。

你的问题 :

所以如果我们在非池内存AND池内存中使用“new”创build一个对象,并且基于上面的定义,我们也会引用它。 当我们这样做时,JVM是否也应该返回相同的参考?

Ans :当你使用new关键字创build一个新的string对象时,生成的地址将是一个堆地址,而不是一个string常量池地址。 而且这两个地址是不同的。

问题

 String one = new String("test"); String two = "test"; System.out.println(one.equals(two)); // true System.out.println(one == two); // false 

以前的陈述是否意味着它们将被放入池内存中,但是在使用新的操作符时会简单地跳过?

:是的,你的假设是正确的。 当程序员使用新的关键字时,JVM将简单地忽略string常量池,并在堆中创build一个新副本。 因此这两个地址是不一样的。