字符串常量池

时间:2013-01-04 03:19:53

标签: java

正如这些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运算符时被跳过?

5 个答案:

答案 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)

创建字符串文字

  1. 每次创建字符串文字时,JVM都会检查 字符串常量池优先

  2. 如果字符串已经存在于池中,则引用 返回池实例

  3. 如果池中不存在字符串,则使用新字符串 创建实例并将其放置在池中

示例

    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。