2013-05-08 71 views
12

我想了解Java字符串是如何不可變的。我認爲這應該是一個簡單的概念,但在閱讀了幾個在線網頁後,我仍然不太明白。Java字符串如何工作

我不明白Java字符串是如何「不可變的」。目前,我有以下代碼:

public static void main(String[] args) { 

    String name = "Jacob Perkins"; 

    System.out.println(name); 

    name = name + "!"; 

    System.out.println(name); 

} 

我的輸出如下:

Jacob Perkins 
Jacob Perkins! 

爲什麼一個字符串應該是這種情況的發生是不可變的?爲什麼我能夠爲字符串重新賦值?

+0

'String' * variables *不是不可變的(因爲它們是不同的!)您已經創建了一個新的字符串並將其引用賦給了變量'name'。 – dlev 2013-05-08 04:11:12

+0

我還是不明白。爲什麼我會用Java字符串看到「不可變的」一詞? – user2301187 2013-05-08 04:13:04

+0

@ user2301187:兩個變量可以指向同一個字符串對象。如果字符串是可變的,則可以通過其他變量的引用來看到一個變量對字符串的更改。因爲它們不是,所以每個變量都知道它指向的字符串不能在「它看起來不會改變」的時候改變。這是因爲可變字符串會令人感到恐懼並且增加了很多複雜性,例如你必須記得每當你想要一個不會改變的副本的時候就創建一個字符串的副本,或者以後會發生奇怪的事情,這也可能是不安全的事情! – Patashu 2013-05-08 04:15:36

回答

34

讓圖像解釋這個給你:

String example

在左邊,你有變量,這實際上是一個參考

  1. String name = "Jacob Perkins;"創建了字符串「Jacob Perkins」,並且name指向它。
  2. name = name + "!";一個新的字符串「Jakob Perkins!」被創建,現在引用指向新的String。但是,舊的不變,因爲字符串是不可變的。
+4

+1爲視覺:) – renz 2013-05-08 04:23:12

+2

+1圖片! – MadProgrammer 2013-05-08 04:24:13

+0

好的,謝謝。我認爲視覺幫助。 – user2301187 2013-05-08 04:26:09

1

只有變量引用更改,String對象纔是不可變的。

在你的例子中,「雅各布珀金斯」對象依然存在,一個新對象「雅各布珀金斯!」被創建。

name變量指向新對象。

0

實際發生的情況是創建了3個String對象。 「雅各布珀金斯」,「!」和「雅各布帕金斯!」。你沒有真正修改「雅各布珀金斯」的例子。您只是將名稱變量的引用從「Jacob Perkins」實例更改爲「Jacob Perkins!」。

+0

我不明白「改變名稱變量的引用」是什麼意思。 – user2301187 2013-05-08 04:16:19

+0

在第一個println()中,name變量指向「Jacob Perkins」字符串對象。該對象並沒有真正改變,因爲字符串是不可變的。相反,創建另外兩個新的String對象,「!」和「雅各布帕金斯!」。然後名稱變量指向「Jacob Perkins!」。 您實際創建了3個String對象,其中沒有一個被靜音。 – renz 2013-05-08 04:22:03

0
String name = "Jacob Perkins"; 

String name2 = name + "!"; 
name.substring(5); // or wather syntax is 

那些不改變

5

字符串本身,一旦創建,就不能再改變變量名。你的代碼示例確實是與從的以前的內容構建一個字符串和一個驚歎號代替字符串中。 (中原來的內容,這是不再被任何變量引用,最終會被垃圾收集器收穫。)

如果你要檢查編譯後的代碼(或通過其與調試步驟)你會發現你的name + "!"表達式已經被編譯成了一個StringBuilder對象的創建以及該對象的一些操作。

也就是說,是不可改變的,但變量沒有。其值改變,指向不同的字符串。字符串本身從不改變。

0

在Java中有引用和有價值觀。

當你說

String foo = "John Smith";

foo是一個變量,保存了一個參考。參考指向包含「John Smith」的對象或值。

該變量保持的引用是可變的。我可以這樣做:

foo = "Jack Smith";

而且我已經變異了參考。但是,如果我寫這樣的代碼:

String foo = "John Smith"; 
String bar = foo; //bar's reference is a copy of foo's reference - the same value 
foo = "Jack Smith"; 
System.out.println(bar); //prints John Smith 

我們看到,即使我們改變了富,酒吧並沒有改變。爲什麼?簡單地說,當我們寫foo = "Jack Smith";時,我們讓foo指向一個新的String。我們沒有通過foo達到並修改字符串,因爲Java中沒有任何方法發生變異,或者可以對字符串進行變異。而是返回一個新的字符串,並將該變量指向新的也是不可變的字符串。這樣,String變量「指向」的對象永遠不能被任何東西修改,只能通過該變量進行修改。這是它保證的Java語言的一個重要屬性。

1

也許這會幫助你理解。

假設你有一個類Point(java.awt.Point)。 比方說,你有一個實例號碼:

Point p = new Point(0,0); 

然後你讓創建一個新的變量y引用同一個物P爲:

Point y = p; 

如果你改變p的值,還修改y 。因爲類Point是可變的。

p.setLocation(1,1); 

它使得y也引用位置1,1。

使用String類它不會發生。

String a = "123"; 
String b = a; 

如果你使a = a +「4」; a的新值將是「1234」,但b仍然是「123」;

他們所引用的對象沒有改變,只是a指向另一個對象。