为什么这些字符串的str == str.intern()结果不同?

时间:2015-08-14 01:25:07

标签: java string string-interning

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。为什么结果不同?

4 个答案:

答案 0 :(得分:20)

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

String#intern()的javadoc声明它返回

  

调用实习方法时,如果池已包含   字符串等于String确定的此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

答案 1 :(得分:4)

因为您的作业不会从intern pool重新读取而且Java General error: 1 no such index: stores_category_id_index (SQL: DROP INDEX stores_category_id_index) 是不可变的。考虑

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

答案 2 :(得分:1)

之前提到的有关该池的大量答案,并使用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()的实际地址。

答案 3 :(得分:0)

让我添加一些更有趣的内容:

  1. OpenJDk 8是真实的;
  2. Oracle JDK 6是true,true;

所以我认为正确的答案是:

不同供应商的jvm或jvm版本可能具有不同的实现(语言规范不强制执行该操作)

在Oracle JDK 8中(我想您正在使用): 字符串“ java”已在池中(由java.lang.Version#laucher_name加载),并且字符串池仅存储引用,而不存储对象。

但是在OpenJDK中,laucher_name是“ openJDK”;在Oracle JDK 6及更低版本中,字符串池会将字符串对象复制到其目录中