2012-09-02 64 views
1

我的應用程序創建了大量的類的實例,比如A類的所有實例都包含一個字符串,其中大部分包含相同的字符串依靠Java字符串複製上寫

class A { 
    String myString; 
} 

我知道JVM使「所有等於字符串」指向只存儲一次的相同字符串。如果我的A實例之一的myString字段被覆蓋,則對原始字符串的引用將被對新字符串值的引用所替代,並且所有工作均按預期工作,就好像每個實例都有一個字符串副本。

這種行爲是需要一個兼容的JVM,或者是一個諸如此類的改良可以從一個JVM切換到另一個,或因版本的JVM?
另一種方式把問題:設計higly冗餘(基於字符串的)數據結構時,應一個上寫機制副本只能依靠或者是adviceable到位的東西在應用程序級別?

+1

Java字符串是不可變的 - 創建後無法更改。當您將一個字符串變量分配給另一個字符串時,您正在分配一個POINTER。如果更改了一個指針,則其他所有先前分配的指針變量保持不變,並仍然處理原始String。沒有「寫入時複製」已完成或需要。 –

+0

這個行爲在JVM規範中非常明確。打破這將導致巨大的問題。 –

+0

與其他語言一樣,我認爲節省內存是由thoruhg COW完成的。好吧,現在我明白這是通過指向不可變對象的指針獲得的。我回去糾正這個問題。 – AgostinoX

回答

0

爲@Hot舔說:string是不可改變的,所以沒有地方談寫時複製。另外,當您使用可變對象時,您必須意識到「寫入時複製」可能無法在客戶端環境中使用。

,當你創建大量的對象,可能是很重要的另一件事。每個對象包含幾個字節的頭部,指針等,如果我沒有記錯的話,空對象就像20個字節左右。當我們談論很多包含屬性的對象時,它開始變得非常重要。需要注意的是,當你措施,這是造成問題,那麼你需要做的在應用層的東西(輕量化設計模式,採用流XML解析器等)。

1

的這另一個方面是,你的字符串將不相同的,如果它們被創建動態地(例如,通過解析器分配)。如果空間是一個問題,請檢查String.intern():

String a = String.valueOf('a') + "b"; 
String b = a.intern(); 
String c = "ab"; 
// now b == c is true 
+0

'「ab」'保證已經被實施。你也可以調用'a.intern'而不是'String.intern(a)'。 – oldrinb

+0

...更不用說編譯器可以將''a「+」b「'合併到'」ab「中,以便不需要'intern'。 – oldrinb

+0

謝謝!代碼現在符合我的意圖。 –

0

事實上,String是常規對象。

String a = "test"; 
String b = a; 

不正是同樣的事情:

StringBuffer a = new StringBuffer("test"); 
StringBuffer b = a; 

那就是:在這兩種情況下,B是第二個參照,這是不是由於不變性。

不變性發揮作用
所以,你總是處理兩個指向相同數據的指針。現在,如果這個類是不可變的,那麼你可以忘記它:沒有人會在你的鞋子上改變你的數據,並不是因爲你有自己的副本,而是因爲共享副本是不可變的。你甚至可以認爲你有一個字符串的副本,但實際上一個副本從來沒有存在,因爲String b = a;做它爲每個對象做的事情:唯一引用的副本。