簡體   English   中英

為什么String.intern()在JDK8和JDK9下返回不同的結果?

[英]Why does String.intern() return different results under JDK8 and JDK9?

以下代碼在JDK8和JDK9下具有不同的結果。

public static void main(String[] args) {
    String s = new String("1");
    s.intern();
    String s2 = "1";
    System.out.println(s == s2);

    String s3 = new String("1") + new String("1");
    //String s3 = "1" + "1";
    s3.intern();
    String s4 = "11";
    System.out.println(s3 == s4);
    System.out.println(s3.equals(s4));
}

在JDK8(“1.8.0_172”版本)下,代碼返回:

false true true

但在JDK9(“9.0.1”版本)下,代碼返回:

false false true

我檢查了兩個JDK版本,它們是正確的。為什么代碼有不同的結果? 我的程序有什么問題嗎?

結果取決於在調用s3.intern()之前String“11”是否已經在String池中。

如果不是, s3.intern()會將s3添加到池中並返回s3 在那種情況下, s4也將被賦予規范表示“11”,因為它是用字符串文字初始化的。 因此s3==s4將是true

如果是, s3.intern()將返回規范表示“11”,這與s3不是同一個實例。 因此s3==s4將是false

我沒有JDK9版本來測試你的代碼,但是如果這是你得到的輸出,它暗示JDK9源代碼中某處在你的main之前執行,出現了“11” String文字,它增加了池中的String

JDK8中的情況並非如此。

在兩種情況下,使用“1” String測試都會給出false ,因為在將String “1”傳遞給new String("1")String構造函數時,會將String “1”添加到池中。 因此, s.intern()不會將s引用的String添加到池中,並且String s2 = "1"; 是一個與s不同的例子。

當試圖理解這種行為時, intern的Javadoc很方便:

String java.lang.String.intern()

返回字符串對象的規范表示。

最初為空的字符串池由String類私有維護。

調用實習方法時, 如果池已經包含等於此字符串對象的字符串(由equals(Object)方法確定),則返回池中的字符串。 否則,將此String對象添加到池中,並返回對此String對象的引用。

...

所有文字字符串和字符串值常量表達式都是實體。

伊蘭的答案很接近。 正如他所確定的那樣, 字符串文字被實習的關鍵問題。

我有一個很好的權限,一些最近的JVM懶惰地執行String文字的實習,它發生在第一次運行時使用文字之前。 告訴此事的人說這是/是新行為。

所以實際的解釋似乎是Java 9是在引入這種新的“懶惰”行為時,這解釋了OP觀察到的Java 8和Java 9之間的區別。

(我將試着看看OpenJDK源代碼中發生了什么......)

暫無
暫無

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

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