深入分析String類

2020-10-17 11:00:03

可以說字串操作是計算機程式設計中最為常見的行為

不可變的String

根據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)分別指向各自的物件,如圖

s1
歐文
s2
艾弗森
s3
NB

執行第12行賦值語句後,並不是修改了s1所指的String物件(歐文),而是修改了參照s1,使其指向參照s2所指的String物件(艾弗森),如圖

s1
歐文
s2
艾弗森
s3
NB

執行第15行語句時,臨時的StringBuilder物件會連線s2與s3所指的物件,並呼叫toString方法建立一個String物件賦值給參照s1,即參照s1會指向這個新建立的String物件,如圖

s1
艾弗森NB
歐文
艾弗森
s2
s3
NB

從執行的過程可以看出,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設計為不可變呢
其最大的好處就是可以實現資源共用,在對執行緒操作的時候,可以將其認為不可變的,而不用擔心其他執行緒會對其進行修改

要點總結

  • String類是不可變類,其物件一旦建立,就不可修改。
  • String類那些看似修改字元序列的方法實際上都是新建立的String物件,而不是修改自身物件
  • 由於String物件是不可變的,因此其具有執行緒安全性,可以自由地實現共用