【发布时间】:2019-08-03 18:44:05
【问题描述】:
考虑:
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 方法时,如果池中已经包含一个与该 String 对象相等的字符串,由 equals(Object) 方法确定,则返回池中的字符串。否则,将此 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
- 由于池中不存在
"Cattie & Doggie",s1.intern()会将当前对象引用放到池中并返回自己,所以s1.intern() == s1; -
"Cattie & Doggie"现在已经在池中,所以字符串文字"Cattie & Doggie"将只使用池中的引用,实际上是s1,所以我们又得到了true; -
new StringBuilder().toString()将创建一个新实例,而"java"已经在池中,然后在调用s2.intern()时将返回池中的引用,因此s2.intern() != s2和我们有false; -
new String()也会返回一个新实例,但是当我们尝试s3.intern()时,它会返回池中先前存储的引用,实际上是s1所以s3.intern() != s3和我们有false; - 正如 #2 已经讨论过的,字符串文字
"Cattie & Doggie"将返回已经存储在池中的引用(实际上是s1),所以s3 != "Cattie & Doggie"和false再次出现。
感谢@Sunny 提供获取所有interned 字符串的技巧。
【问题讨论】:
标签: java string-interning