字符串常量池

2022-09-01 14:17:01

正如这些Stackoverflow问题中所解释的那样:问题1问题2,我理解“字符串文本”在以下情况下被扣留

String s = "abc"; 

并且在以下情况下,JVM 将创建一个新的 String 对象,而不是使用字符串池中的现有对象:

String s = new String("abc");

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

当编译器遇到 String 文本时,它会检查池以查看是否已经存在相同的字符串。如果找到匹配项,则对新文本的引用将定向到现有 String,并且不会创建新的 String 文本对象。

在这种情况下,由于关键字“new”,我们实际上最终会得到一个稍微不同的行为。在这种情况下,对 String 文本的引用仍被放入常量表(字符串文本池)中,但是,当您使用关键字“new”时,JVM 必须在运行时创建一个新的 String 对象,而不是使用常量表中的对象。

因此,如果我们在使用“new”创建对象时也将引用放在非池内存中,并且基于上述定义。当我们这样做时,JVM难道不应该也返回相同的引用吗?

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

System.out.println(one.equals(two)); // true
System.out.println(one == two);      // false

因为在声明 String 文本时,它将已经存在于池中?因此应该返回相同的引用并打印 true?或者前面的语句是否意味着它们将被放入池内存中,但在使用运算符时只是跳过?String three = "test";new


答案 1

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

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)twoone

在此示例中,正好有两个由值 “test” 创建的 s:一个保留在常量池中,并在表达式中使用文本时引用;另一个由 “new” 运算符创建并分配给引用 。String"test"one

编辑

也许你对这句话感到困惑:

当编译器遇到 String 文本时,它会检查池以查看是否已经存在相同的字符串。

请注意,这可以更清楚地说明为:

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

仅当字符串被显式隔离或通过类使用文本时,才会将其放入池中。因此,例如,如果您有此方案:

String te = "te";
String st = "st";

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

则当 a 与值一起存在时,表示字符串将不存在于池中,因为文本从未出现过。Stringtest"test"


答案 2
    //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 !!!