2011-04-23 48 views
3

字符串是不可變的,因爲它們存儲在一個常量字符串池中。那麼,stringbuilder對象在哪裏創建? 說,我創建了兩個字符串生成器對象Stringbuilder對象在哪裏創建?

StringBuilder s1 = new StringBuilder("abc"); 
StringBuilder s2 = new StringBuilder("abc"); 

我會在堆內存2個獨立的物體結束了右翼的包含值「ABC」?

+2

字符串不是不可變的,因爲有一個字符串常量池,反過來:字符串常量池是可能的,因爲字符串是不可變的。 – delnan 2011-04-23 17:24:06

+1

@Hristo:他們根本不是同一個對象。 (事實上​​,它們不是首要的對象 - 它們是變量,但是它們指向不同的對象。)如果你調用's1.append(「foo」)',那麼這不會影響所引用的對象通過's2'。 – 2011-04-23 17:26:48

+1

@Hristo - 每次都會創建兩個單獨的'StringBuilder'實例:) – 2011-04-23 17:27:28

回答

3

字符串的不變性與常量字符串池無關。或者說,他們是不可變的字符串池是有用的,但沒有必要爲他們是不可變的字符串池。

請注意,通常只有編譯時常量纔會在字符串池中結束 - 除非您致電intern()。因此,例如,如果您有:

char[] x = { 'a', 'b', 'c' }; 
String s1 = new String(x); 
String s2 = new String(x); 

然後s1s2表示相同字符串,但不同的對象。

雖然創建兩個StringBuilder對象只是創建兩個對象。 StringBuilder中的內容的確切實現細節可以在各個版本之間輕鬆更改,我不知道其中的詳細信息,但它可能很容易就是從傳遞給構造函數的字符串創建的char[]。 (我相信這是對JDK 1.6的情況下,無論如何。)

0
String str1 = "Java" 
String str2 = "Java" 

所以,str1和STR2都指向在文字池相同的「Java」。

String str3 = new String("Java"); 
String str4 = new String("Java"); 

STR3和STR4沒有指向同一個位置,但有獨立的內存分配。

StringBuilder s1 = new StringBuilder("abc"); 
StringBuilder s2 = new StringBuilder("abc"); 

s1和s2不指向相同的內存位置。

因此,只要你說「」,它會爲該變量創建一個單獨的內存。

您可以通過在控制檯上顯示其地址來測試它。

+0

在第二種情況下,他們爲什麼不能指向同一位置?無論如何他們是字符串,如果你讓他們引用一個新的字符串,一個新的字符串對象將始終創建! – phoenix 2011-04-23 17:38:00

+0

@鳳凰,不,他們不指向相同的位置。你可以通過打印出兩個字符串對象的地址來檢查它 – Shankar 2011-04-23 17:39:43

+0

我知道它們不指向同一個對象。但我的問題是爲什麼他們不能? String s1 = new(「abc」)String s2 = new(「abc」)。所以現在即使s1和s2指向同一個對象也不會傷害到正確的!因爲我分配s1 =「def」的那一刻就創建了一個新的對象..那麼爲什麼虛擬機不檢查一個字符串對象是否已經存在,併爲它分配任何新的字符串對象?基本上我想知道爲什麼你的答案中的第一種方法和第二種方法之間的差異?爲什麼爲第二個創建2個對象? – phoenix 2011-04-23 17:45:55

0

常量池存儲在源代碼中定義爲文字(用雙引號括起來)的字符串。 非文字字符串不存儲在CP中。他們只是使用一個底層的char數組,並確保它永遠不會被寫入。

一個StringBuilder分配這樣一個數組,然後把它交給一個新創建的String對象。

+0

除了字面字符串,編譯時常量字符串表達式也存儲在常量池中,如'「​​Hello」+ 5'。 – 2011-04-23 20:24:56