为什么这些字符串的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 。 为什么结果不同?

行为差异与StringBuilderStringBuffer之间的差异无关。

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 

要返回falseintern()调用必须返回不同的引用值,即。 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()的实际地址。