2013-01-23 23 views
10

問題歸結爲以下代碼:Java字符串interning,什麼保證?

// setup 
String str1 = "some string"; 
String str2 = new String(str1); 
assert str1.equals(str2); 
assert str1 != str2; 
String str3 = str2.intern(); 

// question cases 
boolean case1 = str1 == "some string"; 
boolean case2 = str1 == str3; 

確實Java標準給予任何保證關於case1case2值? 鏈接到Java規範的相關部分將是當然的不錯。

是的,我看着這麼發現所有的「類似的問題」,並沒有發現重複的,因爲沒有我發現回答了這個問題這樣。不,這是不是與==更換equals「優化」的字符串比較的誤導想法。

+2

如果它不是一個無用的優化企圖,是什麼呢? –

+0

@dystroy我有特定的情況下爲約標準化使用文件名進行同步,並且如果實習字符串是安全爲目的,或如果共享'地圖<字符串,對象>將需要fileNameToLockObjectMap'。不確定的是,我最終在這種情況下使用了一個Map(並且不會再改變)。 – hyde

+0

鎖定字符串不是一個好主意。很可能你會有意想不到的後果。 –

回答

13

這是您的JLS報價,Section 3.10.5

每個字符串是String類的一個實例(第4.3.1節, §12.5)的參考(4.3節)(§4.3.3) 。字符串對象具有一個常數值。 字符串文字,或者更一般地,是 常量表達式(§15.28)-are「實習」,以便共享獨特 情況下,使用該方法的String.intern的值的字符串。

因此,由編譯單元(第7.3節)的測試程序:

package testPackage; 
class Test { 
     public static void main(String[] args) { 
       String hello = "Hello", lo = "lo"; 
       System.out.print((hello == "Hello") + " "); 
       System.out.print((Other.hello == hello) + " "); 
       System.out.print((other.Other.hello == hello) + " "); 
       System.out.print((hello == ("Hel"+"lo")) + " "); 
       System.out.print((hello == ("Hel"+lo)) + " "); 
       System.out.println(hello == ("Hel"+lo).intern()); 
     } 
} 

class Other { static String hello = "Hello"; } 

和編譯單元:

package other; 

public class Other { static String hello = "Hello"; } 

產生輸出:真真真真假真

該實施例說明六個點:在同一個包相同的類(§8)內

文字串(§7) 表示相同的字符串對象(第4.3.1節)的引用。在同一封裝不同類中的

文字字符串表示 引用相同的字符串對象。在不同的包 不同類中的

文字字符串同樣表示爲相同字符串對象的引用。

通過常量表達式計算的字符串(§15.28)在編譯時計算得到,然後視爲它們是文字。在運行時通過串聯計算

字符串被新創建,並因此 不同。的明確實習一個計算 串的結果是相同的字符串作爲任何現有的預文字串與 相同的內容。

與實習生的JavaDoc相結合,並且您有足夠的信息來推斷您的兩個案例都將返回true。

+0

它是如何在多線程環境中工作的,例如。當intern()在多個線程中同時多次調用時。我想這是照顧的,但這只是一個猜測。你對此有更多瞭解嗎? – Alpedar

+2

@Alpedar - 實習生的實施是本地和平臺的依賴。我認爲它是基於JavaDoc的線程安全的,但它們不能保證(我發現)在官方文檔中支持這一點。 – Perception

5

我覺得API的String.intern提供足夠的信息

串,初始爲空池,由String類私人維護。

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

因此,對於任何兩個字符串s和t,當且僅當s.equals(t)爲真時,s.intern()== t.intern()才爲真。

所有文字字符串和字符串值的常量表達式都被執行。字符串文字在Java™語言規範的第3.10.5節中定義。

相關問題