[Java基礎]String 為什麼是不可變的?

Duancf發表於2024-07-29

關於這個問題,網上有人說,是因為String類被寫成final或者String中的成員變數value陣列被寫成final,但其實並不是,下面做一個實驗

public final class MyString {
    public final char[] value = {'z'};
}

首先我們定義了一個類Mystring,並且類和成員變數都被設定成final

public class Main {
    public static void main(String[] args) {
        MyString myString = new MyString();
        System.out.println(myString.value);
        myString.value[0] = 'a';
        System.out.println(myString.value);
        myString.value[0] = 'b';
        System.out.println(myString.value);
    }
}

執行結果

z
a
b

這說明僅僅把類和成員變數設定成final無法實現不可變,為了實現不可變我們還需要把這個成員變數設定成private不可見。

繼續我們的實驗

public final class MyString {
    private final char[] value = {'z'};
}

這時再去執行上面的main函式,有如下結果,

E:\MIT6.830\Test_7\src\Main.java:12:36
java: value 在 MyString 中是 private 訪問控制

這時候我們無法直接修改value的值,但是這就可以了嗎?當然還沒有

為了保證string的不可變我們還要繼續做到以下幾點

  • 首先設定內部成員變數的訪問修飾符為private,這樣就無法在類的外部直接訪問到這個成員變數
  • 其次我們必須保證String類不提供成員方法去修改value,String的成員方法不是直接修改value而是透過新建一個String,並且把舊的string中的值複製到新的string物件中去。
  • 在value上加final保證這個陣列的引用不會被修改而指向另一個陣列
  • 在String上加final保證String沒有子類,因為子類可能提供方法去修改value,子類可以賦值給父類引用進而破壞String的不可變特性

儲存字串的陣列被 final 修飾且為私有的,並且String 類沒有提供/暴露修改這個字串的方法。
String 類被 final 修飾導致其不能被繼承,進而避免了子類破壞 String 不可變。

相關文章