2012-01-19 41 views
5

如果String S IN的Java是不可改變的,那麼怎樣才能爲寫:Java的不可改變的字符串混亂

String s = new String(); 
s = s + "abc"; 
+2

因爲's'不是'final'。 – SLaks

+1

s不是字符串,它是一個包含對字符串引用的容器。首先,它保存對新String()返回的字符串的引用,然後將其更改爲保存由新String()+「abc」返回的字符串的引用,即另一個字符串的引用。 – ignis

回答

7

你的字符串變量不是字符串。這是一個String實例的參考。

見自己:

String str = "Test String"; 
System.out.println(System.identityHashCode(str)); // INSTANCE ID of the string 

str = str + "Another value"; 
System.out.println(System.identityHashCode(str)); // Whoa, it's a different string! 

的情況下,str變量指向是單獨不可變的,但是變量可以指向你想要字符串的任何實例。

如果你不希望它可以重新分配STR指向一個不同的字符串實例,聲明它最後:

final String str = "Test String"; 
System.out.println(System.identityHashCode(str)); // INSTANCE ID of the string 

str = str + "Another value"; // BREAKS HORRIBLY 
+0

將'String's轉換爲'Object's有什麼意義? – Natix

+0

簡單。 str.toString()返回字符串。調用((Object)str).toString()爲我們提供了實際的實例ID。這是爲了演示目的。 –

+2

不,它沒有。 Java中的方法是虛擬的,將對象轉換爲超類型在這裏沒有效果。 'String'的被覆蓋'toString()'方法的實現仍然會被調用。你需要調用'System.identityHashCode(str)'來得到一個對象的原始的基於身份的hashCode。 – Natix

8

字符串不變。
這意味着實例String不能更改。

您正在更改s變量以引用不同的(但仍是不可變的)String實例。

0
String s = new String(); 

創建一個新的不可變的空字符串變量「s」引用它。

s = s+"abc";    

創建一個新的不可變的字符串;空字符串和「abc」,變量「s」的連接現在引用這個新對象。

1

一成不變的類是那些方法可以改變它們的字段,例如:

Foo f = new Foo("a"); 
f.setField("b"); // Now, you are changing the field of class Foo 

但在不可變的類,例如字符串,創建後無法更改對象,但當然是,您可以將引用重新分配給另一個對象。例如:

String s = "Hello"; 
s.substring(0,1); // s is still "Hello" 
s = s.substring(0,1); // s is now referring to another object whose value is "H" 
0

只是爲了澄清,當你說s = s +「abc」; 這意味着,創建一個新的String實例(由s和「abc」組成),然後將該新的String實例分配給s。所以s中的新參考文獻與舊文獻有所不同。

請記住,變量實際上是對某個特定內存位置的對象的引用。即使您將變量更改爲在不同位置引用新對象,該位置的對象仍保留在該位置。

2

第一個答案是絕對正確的。您應該將其標記爲已回答。

s = s+"abc"不附加到s對象。它會創建一個新的字符串,其中包含s對象(其中沒有)和「abc」中的字符。

如果字符串是可變的。它會有像在StringBuilder和StringBuffer上的append()和其他這樣的變異方法。

Josh Bloch的有效Java對不可變對象及其價值進行了很好的討論。

0
String s = new String(); 

String對象("")創建。變量s引用該對象。

s = s + "abc"; 

​​是一個字符串(其只不過是一個String對象,這是隱式地創建並保持在字符串的池),使得它可以再利用(因爲字符串是不可變的,因此是恆定的)。但是當你做new String()是完全不同的,因爲你明確地創建對象,所以不會在池中結束。你可以通過一些被稱爲實習的東西扔在游泳池裏。

所以,s + "abc"因爲在這一點上級聯和空字符串("")和​​並沒有真正創建一個新的String對象,因爲最終的結果是​​這已經是在游泳池。因此,最後變量s將引用池中的文字​​。

-2

我相信你們都做得比所需要的要複雜得多,而這隻會讓那些試圖學習的人感到困惑!

製造物體中的Java不可變的主要好處是,它可以通過引用傳遞(例如另一種方法或使用賦值運算符分配),而不必擔心下游改變到對象中導致問題當前的方法或上下文。 (這比大約一個對象的線程安全任何對話非常不同。)

爲了說明,創建傳遞一個字符串作爲參數傳遞給一個單獨的方法的應用程序,並修改該方法中的字符串。在被調用方法的末尾打印字符串,然後控制權返回到調用方法。字符串會有不同的值,這是因爲它們指向不同的內存位置,這是「更改」不可變String的直接結果(創建一個新指針並將其指向後面的新值)。然後創建一個應用程序,除了使用StringBuffer之外,這些應用程序的功能是不可變的。 (例如,您可以追加到StringBuffer中進行修改。)打印的StringBuffers將具有相同的值,這是因爲它是(a)通過引用傳遞的,因爲Java會將所有傳遞給方法的對象作爲參數傳遞給(b)可變的。

我希望這可以幫助那些正在閱讀本主題並嘗試學習的人!