String中intern的方法
intern
public String intern()
返回字串物件的規範化表示形式。
一個初始時為空的字串池,它由類 String 私有地維護。
當呼叫 intern 方法時,如果池已經包含一個等於此 String 物件的字串(該物件由 equals(Object) 方法確定),則返回池中的字串。否則,將此 String 物件新增到池中,並且返回此 String 物件的引用。
它遵循對於任何兩個字串 s 和 t,當且僅當 s.equals(t) 為 true 時,s.intern() == t.intern() 才為 true。
所有字面值字串和字串賦值常量表達式都是內部的。
返回:
一個字串,內容與此字串相同,但它保證來自字串池中。
———————————————————————————————————————
儘管在輸出中呼叫intern方法並沒有什麼效果,但是實際上後臺這個方法會做一系列的動作和操作。在呼叫”ab”.intern()方法的時候會返回”ab”,但是這個方法會首先檢查字串池中是否有”ab”這個字串,如果存在則返回這個字串的引用,否則就將這個字串新增到字串池中,然會返回這個字串的引用。
可以看下面一個範例:
String str1 = "a"; String str2 = "b"; String str3 = "ab"; String str4 = str1 + str2; String str5 = new String("ab"); System.out.println(str5.equals(str3)); System.out.println(str5 == str3); System.out.println(str5.intern() == str3); System.out.println(str5.intern() == str4);
得到的結果:
true
false
true
false
為什麼會得到這樣的一個結果呢?我們一步一步的分析。
第一、str5.equals(str3)這個結果為true,不用太多的解釋,因為字串的值的內容相同。
第二、str5 == str3對比的是引用的地址是否相同,由於str5採用new String方式定義的,所以地址引用一定不相等。所以結果為false。
第三、當str5呼叫intern的時候,會檢查字串池中是否含有該字串。由於之前定義的str3已經進入字串池中,所以會得到相同的引用。
第四,當str4 = str1 + str2後,str4的值也為”ab”,但是為什麼這個結果會是false呢?先看下面程式碼:
String a = new String("ab");
String b = new String("ab");
String c = "ab";
String d = "a" + "b";
String e = "b";
String f = "a" + e;
System.out.println(b.intern() == a);
System.out.println(b.intern() == c);
System.out.println(b.intern() == d);
System.out.println(b.intern() == f);
System.out.println(b.intern() == a.intern());
執行結果:
false
true
true
false
true
由執行結果可以看出來,b.intern() == a和b.intern() == c可知,採用new 建立的字串物件不進入字串池,並且通過b.intern() == d和b.intern() == f可知,字串相加的時候,都是靜態字串的結果會新增到字串池,如果其中含有變數(如f中的e)則不會進入字串池中。但是字串一旦進入字串池中,就會先查詢池中有無此物件。如果有此物件,則讓物件引用指向此物件。如果無此物件,則先建立此物件,再讓物件引用指向此物件。
當研究到這個地方的時候,突然想起來經常遇到的一個比較經典的Java問題,就是對比equal和==的區別,當時記得老師只是說“==”判斷的是“地址”,但是並沒說清楚什麼時候會有地址相等的情況。現在看來,在定義變數的時候賦值,如果賦值的是靜態的字串,就會執行進入字串池的操作,如果池中含有該字串,則返回引用。
執行下面的程式碼:
String a = "abc";
String b = "abc";
String c = "a" + "b" + "c";
String d = "a" + "bc";
String e = "ab" + "c";
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a == d);
System.out.println(a == e);
System.out.println(c == d);
System.out.println(c == e);
執行的結果:
true
true
true
true
true
true
執行的結果剛好驗證了我剛才的猜想。