为什么这些字符串的str == str.intern()结果不同?
public static void main(String[] args) { String str1 = new StringBuilder("计算机").append("软件").toString(); System.out.println(str1.intern() == str1); String str2 = new StringBuffer("ja").append("va").toString(); System.out.println(str2.intern() == str2); }
结果:
true false
第一个打印为true
,第二个打印为false
。 为什么结果不同?
行为差异与StringBuilder
和StringBuffer
之间的差异无关。
String#intern()
的javadoc声明它返回
调用实习方法时, 如果池已经包含等于此
String
对象的字符串equals(Object)
由equals(Object)
方法确定equals(Object)
,则返回池中的字符串 。 否则,将此String
对象添加到池中,并返回对此String
对象的引用。
从中创建的String
String str2 = new StringBuffer("ja").append("va").toString();
是一个不属于池的全新String
。
对于
str2.intern() == str2
要返回false
, intern()
调用必须返回不同的引用值,即。 String
"java"
已经在池中 。
在第一次比较中, String
“计算机软件”在调用intern()
之前不在字符串池中。 因此intern()
返回与str2
存储的引用相同的引用。 因此引用相等str2 == str2
返回true
。
因为您的分配不会从实习池重新读取,并且Java String
是不可变的。 考虑
String str1 = new StringBuilder("计算机").append("软件").toString(); String str1a = new String(str1); // <-- refers to a different String str1 = str1.intern(); str1a = str1a.intern(); System.out.println(str1a == str1); String str2 = new StringBuffer("ja").append("va").toString(); String str2a = new String(str2); // <-- refers to a different String str2 = str2.intern(); str2a = str2a.intern(); System.out.println(str2a == str2);
输出是(正如您所料)
true true
之前提到的关于池的大量答案,并用Oracle链接文档清楚地解释了。
我只是想指出我们在调试代码时可以检查的方式。
String str1 = new StringBuilder("计算机").append("软件").toString(); System.out.println(str1.intern() == str1);//the str1.intern() returns the same memory address the str1 String str2 = new StringBuffer("ja").append("va").toString(); System.out.println(str2.intern() == str2);//the str2.intern() does not return the same memory address the str2
您可以使用任何IDE和debug来检查str1和str1.intern()/ str2和str2.intern()的实际地址。