可以說字串操作是計算機程式設計中最為常見的行為
根據JDK檔案的說法,String類代表字串,Java程式中的所有字串文字(例如"abc")都被實現為此類範例,例如:
String string = "abc";
//相當於:
char[] data = {'a','b','c'};
String str = new String(data);
那為什麼說String類是不可變的,看一段String類中的部分原始碼
哦~,原來是這樣。String類是被final修飾的,所以無法繼承該類。並且,其所有的成員變數都是私有(private)的,而且沒有提供修改私有變數的共有(public)方法,再者,關於對String物件的操作都沒有修改當前物件,而是新建一個物件
例如下面這個substing方法,如果返回值不等於自身,該方法就會建立一個String物件,該物件為擷取後的結果,而不是在原String物件上進行的
可能有些人就來疑問了,誰說的不能修改。看我這個,s1都被我改的毀容了
其實,這只是表面的錯覺而已
起初,3個參照(s1、s2、s3)分別指向各自的物件,如圖
執行第12行賦值語句後,並不是修改了s1所指的String物件(歐文),而是修改了參照s1,使其指向參照s2所指的String物件(艾弗森),如圖
執行第15行語句時,臨時的StringBuilder物件會連線s2與s3所指的物件,並呼叫toString方法建立一個String物件賦值給參照s1,即參照s1會指向這個新建立的String物件,如圖
從執行的過程可以看出,String物件「歐文」、「艾弗森」、「NB」在全程過程中都沒有改變,改變的只是參照s1所指向的內容,也就是s1的值。
下面的程式給予說明,String物件的不可變性。
可以看出,儘管對s1依次呼叫了3個方法(toUpperCase、concat和substring),但是s1指向的String內容始終沒有改變,而s2、s3與s4確實輸出了期望的結果。這是因為,String類提供的一系列操作字串內容的方法都不是在自身物件上進行的,而是新建立一個String物件,例如,當呼叫toUpperCase時,並不是修改s1自身指向的String物件,而是新建立了一個String物件,其內容就是s1內容的大寫形式。因此,這樣既可以滿足對String物件的各種操作要求,又保證了String物件的資料成員不會被外界修改。
那為什麼要把String設計為不可變呢
其最大的好處就是可以實現資源共用,在對執行緒操作的時候,可以將其認為不可變的,而不用擔心其他執行緒會對其進行修改
要點總結