正如这些Stackoverflow问题中所述:question 1& question 2我明白“字符串文字”在interned时是:{/ p>
String s = "abc";
在以下情况下,JVM将创建一个新的String对象,而不是使用String Pool中的现有对象:
String s = new String("abc");
然而,在阅读以下两个类似的陈述之后,我有一个疑问。
当编译器遇到String文字时,它会检查池以查看是否已存在相同的String。如果找到匹配项,则对新文本的引用将定向到现有String,并且不会创建新的String文本对象。
在这种情况下,由于关键字“new”,我们实际上最终会遇到略微不同的行为。在这种情况下,对字符串文字的引用仍然放在常量表(String Literal Pool)中,但是,当你来到关键字“new”时,JVM必须在运行时创建一个新的String对象,而不是使用常量表中的那个。
因此,当我们使用“new”并基于上面的定义创建对象时,我们还在池内存中的非池内存 AND 中放置引用。 当我们这样做时,JVM是否也应该返回相同的引用?:
String one = new String("test");
String two = "test";
System.out.println(one.equals(two)); // true
System.out.println(one == two); // false
因为在声明字符串文字String three = "test";
时它会在池中存在吗?因此应该返回相同的参考和打印真实?或者之前的陈述是否意味着它们将被放入池内存中但只是在使用new
运算符时被跳过?
答案 0 :(得分:29)
也许这有助于您理解:
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)
的引用与引用two
具有相同的值。但是,字符串本身(由这两个引用引用)用于构造一个 new 对象,该对象被分配给引用one
。
在这个例子中,使用值“test”创建了两个String
:在常量池中维护的"test"
,只要在表达式中使用文字one
,就会引用它第二个由“新”运算符创建并分配给引用String te = "te";
String st = "st";
String test = new String(te) + new String(st);
。
也许你对这句话感到困惑:
当编译器遇到String文字时,它会检查池以查看是否已存在相同的String。
请注意,这可能更清楚地表述为:
当编译器遇到字符串文字时,它会检查池中是否存在相同的字符串 。
字符串只有在显式实现或通过类使用文字时才会放入池中。例如,如果您有这种情况:
String
然后当test
存在且值为"test"
时,表示字符串中的字符串不会作为文字{{1从未发生过。
答案 1 :(得分:8)
//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 !!!
答案 2 :(得分:2)
"abc"
将一个对象放入常量池,在编译/类加载时,和new String()
在执行时创建一个新对象。 / em>所以new String("abc")
同时做到了,但处于不同的阶段。
答案 3 :(得分:2)
你的问题:
因此,当我们使用“new”并基于上面的定义创建对象时,我们还在非池内存和池内存中放置引用。当我们这样做时,JVM是否也应该返回相同的引用?:
Ans :使用new关键字创建新的字符串对象时,生成的地址将是堆地址,而不是字符串常量池地址。两个地址都不同。
问题:
String one = new String("test");
String two = "test";
System.out.println(one.equals(two)); // true
System.out.println(one == two); // false
以前的陈述是否意味着它们会被放入池内存中,但只是在使用新运算符时会被跳过?
回答:是的,您的假设是正确的。当程序员使用new关键字时,JVM将忽略关于字符串常量池,并在Heap中创建一个新副本。因此两个地址都不相同。
答案 4 :(得分:0)
创建字符串文字
每次创建字符串文字时,JVM都会检查 字符串常量池优先
如果字符串已经存在于池中,则引用 返回池实例
如果池中不存在字符串,则使用新字符串 创建实例并将其放置在池中
示例
String s1 = "Welcome";
String s2 = "Welcome"; //will not create new instance
字符串文字和字符串对象
String str1 = "Hello World!!";
String str2 = "Hello World!!";
System.out.println(str1 == str2);// true
创建字符串文字str2时,字符串 不再创建“ Hello World”。相反,它是str1 字符串被重用,因为它已经存在于字符串中 恒定池。
由于str1和str2都引用相同的
String str3 = new String("Hello World!!");
String str4 = new String("Hello World!!");
System.out.println(str3 == str4); // false
在这种情况下,将创建新的String对象并 由str3和str4分别引用。因此,str3 == str4为假。 池中的字符串,str1 == str2为true。