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一个新副本。 因此这两个地址是不一样的。