簡體   English   中英

為什么這些字符串的 str == str.intern() 結果不同?

[英]Why are the results of of str == str.intern() for these strings different?

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 聲明它返回

當調用 intern 方法時,如果池中已經包含一個等於該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"已經在池中

在第一次比較中,在調用intern()之前String “計算機軟件”不在字符串池中。 因此intern()返回的引用與存儲在str2引用相同。 因此引用相等str2 == str2返回true

因為您的作業不會從實習池中重新讀取,並且 Java String (s) 是不可變的。 考慮

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並調試來檢查str1和str1.intern()/str2和str2.intern()的實際地址。

讓我添加一些更有趣的東西:

  1. OpenJDK 8 是真的,真的;
  2. Oracle JDK 6 是真的,真的;

所以我認為正確的答案是:

不同供應商的 jvm 或 jvm 版本可能有不同的實現(語言規范不強制如何)

在 Oracle JDK 8 中(我猜你在使用):字符串“java”已經在池中(由 java.lang.Version#laucher_name 加載)並且字符串池只存儲引用,而不是對象。

但是在 OpenJDK 中,laucher_name 是“openJDK”;在 Oracle JDK 6 及以下版本中,字符串池會將字符串對象復制到 itslef 中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM