[英]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.