簡體   English   中英

String.intern()如何工作

[英]String.intern() how to work

package com.zhb.jvm;

/**
 * 
 * @author zhb
 *
 */
public class RuntimeConstantPoolOOM {
    public static void main(String[] args){

        String str1 = "abc";
        System.out.println(str1.intern() == str1);    //true
        String str2 = new String("abcd");
        System.out.println(str2.intern() == str2);    //false

        String str3 =new StringBuilder("math").append("analyze").toString();
        System.out.println(str3.intern() == str3);    //true

        String str4 =new StringBuilder("computer").append("software").toString();
        System.out.println(str4.intern() == str4);    //true

        String str5 =new StringBuilder("jav").append("a").toString();
        System.out.println(str5.intern() == str5);    //false
    }

}

首先,我們可以知道intern()方法的定義。 intern的定義:調用intern方法時,如果池已經包含等於equals(Object)方法確定的thisString對象的字符串,則返回池中的字符串。 否則,將thisString對象添加到池中,並返回對此String對象的引用。

str1.intern == str1為true。 這很容易理解。 str2.intern()== str2這也很容易通過方法的定義來理解。 但是為什么str3.intern()== str3是正確的。實際上,我認為根據定義它是錯誤的。 相反,str5.intern()== str5為假。 我在終端java -version java版本“ 1.7.0_40”中運行命令Java™SE運行時環境(內部版本1.7.0_40-b43)Java HotSpot™64位服務器VM(內部版本24.0-b56,混合模式) )

我想獲得正確答案。非常感謝!

為什么str3.intern()== str3為true

因為,正如您所說:

否則,將thisString對象添加到池中,並返回對此String對象的引用。

你就是這種情況。 該池尚不包含str3(即“ mathanalyze”)。 因此將str3添加到池中並返回。

對於str5,您處於另一種情況:

如果池已經包含等於equals(Object)方法確定的thisString對象的字符串,則返回池中的字符串

因此,執行代碼時,池中已經包含字符串“ java”,這並不奇怪,因為java例如是所有標准類的頂級包的名稱以及所使用的可執行文件的名稱。啟動JVM。 在執行main方法之前,在用於引導應用程序並加載類的代碼中很有可能會使用文字字符串“ java”。

我的看法是,池中默認為字符串"java" 確實,當您在str3上調用intern()時,該詞還沒有在池中,因此將其添加,並且返回的引用為str3 (未創建新對象),因此測試得出true。 相反, "java"已在池中,因此它返回池中對象的引用,這與str5的引用不同。

請注意,您不僅會在使用"java"時觀察到相同的行為,而且還會在所有單個字符中觀察到相同的行為。

測試foo.intern() == foo是一種在調用intern()之前測量foo是否已經在池中的方法。 因此, str3.intern() == str3表示str3尚未在池中。 就這樣。

運行時中某個地方可能存在一個常量字符串"java" ,該常量字符串已在復制之前加載到池中,這就是為什么str5.intern() != str5

這是我通過grep OpenJDK 8源代碼發現的最明顯的情況:

./com/sun/beans/decoder/DocumentHandler.java:        setElementHandler("java", JavaElementHandler.class); // NON-NLS: the element name
./com/sun/tools/example/debug/gui/JDBMenuBar.java:        JDBFileFilter filter = new JDBFileFilter("java", "Java source code");
./com/sun/tools/jdi/SunCommandLineLauncher.java:                "java",
./sun/launcher/LauncherHelper.java:                (progname == null) ? "java" : progname ));
./sun/rmi/server/Activation.java:                        File.separator + "bin" + File.separator + "java";
./sun/rmi/server/Activation.java:                    command[0] = "java";

據我了解,可能存在任何運行時字符串“ java”,這會導致此問題。

    String str5 =new StringBuilder("jav").append("a").toString();
    System.out.println(str5.intern() == str5);    //false

上面這兩個語句只是false ,除了要使用true構成其傳遞的任何其他字符串。

按照Java規范的Intern()。

這將返回字符串對象的規范表示。 最初為空的字符串池由String類私有維護。 調用intern方法時,如果池已經包含等於equals(Object)方法確定的此String對象的字符串,則返回池中的字符串。 否則,將此String對象添加到池中,並返回對此String對象的引用。 因此,對於任意兩個字符串s和t,當且僅當s.equals(t)為true時,s.intern()== t.intern()為true。

所有文字字符串和字符串值常量表達式均已插入。 字符串文字是在Java™語言規范的3.10.5節中定義的。

返回 :具有與該字符串相同的內容的字符串,但保證來自唯一字符串池。

希望對您有幫助。

暫無
暫無

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

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