2013-04-13 81 views
5
 String s1 = new String("string"); 
     String s2 = new String("string"); 

     String s3 = "string"; 
     String s4 = "string"; 

     System.out.println(s1 == s2);  //FALSE 
     System.out.println(s2.equals(s1)); //TRUE 

     System.out.println(s3 == s4);  //TRUE 
     System.out.println(s3.equals(s4)); //TRUE 

是什麼創造s1s3之間的區別? 請讓我知道分配和創建新的String差異

在字符串爲什麼它把這個兩個不同,我們只有String對象即可。 s1和s2具有不同的存儲器地址,而s3和s4具有相同的存儲器地址。 爲什麼它的工作原理基於new operator。?

+0

如果你想讓你的概念在java中清楚字符串請閱讀KathySierra Scjp 6。第六章絃樂在絃樂上有着精彩的解釋意味着沒有人不能更好地解釋她。如果你想要pdf,只需在[email protected]給我發郵件給我。如果別人有興趣,他們也可以給我發郵件。 –

+0

謝謝,剛剛得到它..... – sunleo

回答

5

代表Java源代碼中的字符串文字的String對象會在定義它們的類加載時被添加到共享的String池中。這確保了字符串文字的所有「副本」實際上是相同的對象......即使文字出現在多個類中。這就是爲什麼s3 == s4true

相比之下,當你在new的String中創建一個不同的新的String對象時。這就是爲什麼s1 == s2false。 (這是new的基本屬性,它保證創建並返回一個新的對象...如果它正常完成。)

但是,無論哪種情況,字符串將具有相同的字符,這就是爲什麼equals返回true


雖然重要的是要明白是怎麼回事時,真正教訓是比較Java字符串的正確的方法是使用equals,而不是==

如果您想要安排使用==來測試String對象是否相等,可以使用String.intern方法「實習」它們。然而,你必須一貫地這樣做......而且在各方面實習都是一個昂貴的過程......所以這通常不是一個好主意。

+0

爲什麼實習是一個昂貴的過程? – AmitG

+1

許多因素。 1)有一個哈希表,它使用內存,並在調用'intern'時被探測/更新。 2)每個interned字符串都必須使用弱引用存儲在散列表中。這是額外的內存+ GC開銷。 3)實習字符串存儲在(通常有限的)「permgen」空間中。 GC'ing permgen通常需要完整的GC。 –

+0

很好的解釋。我在某處讀過,Java 1.7字符串不會進入堆的PermGen區域?真的嗎? – AmitG

2

JVM有一個自動優化。除非你專門創建一個新的String對象,而另一個String對象已經有相同的值存在,JVM自動假設一個新的對象不是必須的,並且將一個指針賦給你已經存在的平等String對象。

從本質上講,當你使用第二個選項,這是發生了什麼:

步驟1

第一目標是創建沒有問題。

步驟2

在創建第二對象之前,字符串池檢查的值。 如果該值當前存在,則不需要創建新對象。它只是返回對String對象的引用。

步驟3

而不是被分配一個新對象,但它被簡單地提供給在步驟1中這是爲了節約存儲器取得的對象的引用。

+1

爲什麼downvote? – christopher

3

s1是一個新的String對象,它不屬於任何合併實例的一部分。 s3是來自池的字符串的一個實例。查找java字符串池。看看String上的相關intern()方法。

這個概念並不是java獨有的。其他語言支持String interning。在該相關說明中,彙集常用對象遵循flyweight模式,並不限於字符串。看看Integer.valueOf()。整數也有自己的池。

0

發生這種情況是因爲new運算符強制創建一個新的String實例,而在第二種情況下,因爲String是一個不可變類,JVM爲這兩個變量提供了相同的String實例以節省內存。因爲沒有機會這樣的對象之一會改變,導致第二個改變(不可改變,記得嗎?)這是好的。