String.intern() 的返回解释了

2022-09-02 09:40:58

考虑:

String s1 = new StringBuilder("Cattie").append(" & Doggie").toString();
System.out.println(s1.intern() == s1); // true why?
System.out.println(s1 == "Cattie & Doggie"); // true another why?

String s2 = new StringBuilder("ja").append("va").toString();
System.out.println(s2.intern() == s2); // false

String s3 = new String("Cattie & Doggie");
System.out.println(s3.intern() == s3); // false
System.out.println(s3 == "Cattie & Doggie"); // false

我感到困惑的是,为什么它们的结果与 String.intern()返回值不同,它说:

调用 intern 方法时,如果池中已包含由 equals(Object) 方法确定的与此 String 对象相等的字符串,则返回池中的字符串。否则,此 String 对象将添加到池中,并返回对此 String 对象的引用。

特别是在这两个测试之后:

assertFalse("new String() should create a new instance", new String("jav") == "jav");
assertFalse("new StringBuilder() should create a new instance",
    new StringBuilder("jav").toString() == "jav");

我曾经读过一篇文章,谈论一些实习生先于其他一切,但现在这是一个真正的模糊。special strings

如果有一些字符串,有没有办法得到它们的列表?我只是好奇它们能是什么。pre-interned


更新

多亏了@Eran和@Slaw的帮助,我终于可以解释输出刚刚发生的事情

true
true
false
false
false
  1. 由于池中不存在,因此 s1.intern() 会将当前对象引用放到池中并返回自身,因此"Cattie & Doggie"s1.intern() == s1;
  2. "Cattie & Doggie"现在已经在池中了,所以字符串文本将只使用池中的引用,这实际上是,所以我们再次有"Cattie & Doggie"s1true;
  3. new StringBuilder().toString()将在池中已经存在时创建一个新实例,然后在调用时将返回池中的引用,因此,我们有"java"s2.intern()s2.intern() != s2false;
  4. new String()还将返回一个新实例,但是当我们尝试时,它将返回以前存储在池中的引用,这实际上是如此,我们有s3.intern()s1s3.intern() != s3false;
  5. 正如 #2 已经讨论过的,String literal 将返回已经存储在池中的引用(实际上是 ),因此我们再次返回。"Cattie & Doggie"s1s3 != "Cattie & Doggie"false

感谢您@Sunny提供获取所有字符串的技巧。interned


答案 1

s2.intern()仅当字符串池在该调用之前不包含其值为“java”的实例时,才会返回 引用的实例。JDK 类在执行代码之前会先执行一些 s。“java”必须是其中之一。因此,返回以前暂存的实例,而不是 。s2StringStrings2.intern()s2

另一方面,JDK 类没有插入任何值等于“Cattie & Doggie”的类,因此返回 。Strings1.intern()s1

我不知道任何预先拘留的字符串列表。这样的列表很可能被视为实现细节,在不同的JDK实现和JDK版本上可能会有所不同,因此不应依赖。


答案 2

当在 String 对象上调用 intern() 方法时,它会在池中查找此 String 对象包含的字符串,如果在此处找到该字符串,则返回池中的字符串。否则,此 String 对象将添加到池中,并返回对此 String 对象的引用。

因此,字符串必须已在池中。因此,它给出了假的。java

您可以打印池中的所有字符串

如何打印整个字符串池?

下面是一个示例,用于获取所有字符串(如果您使用的是 openjdk)。


推荐