2012-05-15 13 views
137
String s = "hello"; 
    String backup_of_s = s; 
    s = "bye"; 

在這一點上,備份變量仍然包含原始值「你好」(這是因爲字符串的不變性吧?)。我應該如何複製Java中的字符串?

但是真的安全複製字符串與這種方法(當然不安全複製常規的可變對象),或者更好地寫這個? :

String s = "hello"; 
    String backup_of_s = new String(s); 
    s = "bye"; 

換句話說,這兩個片段之間有什麼區別(如果有的話)?


編輯 - 爲什麼第一個片段是安全的原因:

讓我交代的事情有更詳細一點的基礎上,已經提供的很好的答案(這基本上是集中在問題2個片段之間的性能差異):

字符串在Java中是不可變的,這意味着String對象在構造後不能修改。 因此,

String s = "hello";創建一個新的字符串實例及其地址分配給ss作爲一個參考實例/對象)

String backup_of_s = s;創建一個新的變量backup_of_s並且使得它引用的對象當前初始化它參考s

注:字符串不變性保證這個對象將不會被修改:我們的備份是安全

注2:Java的垃圾回收機制確保該對象將不只要它是由至少一個參考銷燬(在這種情況下backup_of_s)可變

最後,s = "bye";創建另一個字符串實例(因爲永恆的,它是唯一的方法),並修改s變量,以便它現在引用新的對象。

回答

94

由於字符串是不可變的,所以兩個版本都是安全的。然而,後者效率較低(創建一個額外的對象,並在某些情況下複製字符數據)。

考慮到這一點,第一版應該是首選。

+11

不變性與它無關。這只是對象引用的工作方式。我可以提供一個等效的StringBuilder示例。 – GriffeyDog

+1

@BalusC,我無法看到新的String()如何在JVM的字符串池中創建任何東西。只有字符串和通過intern()提交給池的字符串在池中。 – Snicolas

+2

@GriffeyDog:我正在逐字閱讀這個問題。我所說的是,可以安全地發出對字符串對象的引用,而不必擔心有人可能會修改字符串。 – NPE

9

你的第二個版本效率不高,因爲它在沒有必要的時候會創建一個額外的字符串對象。

不變性意味着您的第一個版本的行爲與您期望的一致,因此是首選方法。

12

字符串是immutable objects所以你可以複製它們只是應對對它們的引用,因爲引用的對象不能改變......

所以,你可以在你的第一個例子複製沒有任何問題:

String s = "hello"; 
String backup_of_s = s; 
s = "bye"; 
-10
String str1="this is a string"; 
String str2=str1.clone(); 

這個怎麼樣副本? 我認爲要得到一個新的副本更好,這樣str1的數據將不會受到影響,當str2是參考和修改後的進一步行動。

+3

'字符串'是不可變的。克隆字符串沒有多大意義。 – Vladimir

+11

'String.clone()'不存在... – glen3b

0

第二種情況在字符串池方面效率也不高,您必須在返回引用中顯式調用intern()以使其成爲實際。

相關問題