1. 程式人生 > >【Java核心技術】String、StringBuffer、StringBuilder有什麼區別?

【Java核心技術】String、StringBuffer、StringBuilder有什麼區別?

1 String

(1) String的建立機理
由於String在Java世界中使用過於頻繁,Java為了避免在一個系統中產生大量的String物件,引入了字串常量池。其執行機制是:建立一個字串時,首先檢查池中是否有值相同的字串物件,如果有則不需要建立直接從池中剛查詢到的物件引用;如果沒有則新建字串物件,返回物件引用,並且將新建立的物件放入池中。但是,通過new方法建立的String物件是不檢查字串池的,而是直接在堆區或棧區建立一個新的物件,也不會把物件放入池中。上述原則只適用於通過直接量給String物件引用賦值的情況。

舉例:String str1 = "123"; //通過直接量賦值方式,放入字串常量池
String str2 = new String(“123”);//通過new方式賦值方式,不放入字串常量池

注意:String提供了inter()方法。呼叫該方法時,如果常量池中包括了一個等於此String物件的字串(由equals方法確定),則返回池中的字串。否則,將此String物件新增到池中,並且返回此池中物件的引用。


(2) String的特性
[A] 不可變。是指String物件一旦生成,則不能再對它進行改變。不可變的主要作用在於當一個物件需要被多執行緒共享,並且訪問頻繁時,可以省略同步和鎖等待的時間,從而大幅度提高系統性能。不可變模式是一個可以提高多執行緒程式的效能,降低多執行緒程式複雜度的設計模式。

[B] 針對常量池的優化。當2個String物件擁有相同的值時,他們只引用常量池中的同一個拷貝。當同一個字串反覆出現時,這個技術可以大幅度節省記憶體空間。

2 StringBuffer/StringBuilder

StringBuffer和StringBuilder都實現了AbstractStringBuilder抽象類,擁有幾乎一致對外提供的呼叫介面;其底層在記憶體中的儲存方式與String相同,都是以一個有序的字元序列(char型別的陣列)進行儲存,不同點是StringBuffer/StringBuilder物件的值是可以改變的,並且值改變以後,物件引用不會發生改變;兩者物件在構造過程中,首先按照預設大小申請一個字元陣列,由於會不斷加入新資料,當超過預設大小後,會建立一個更大的陣列,並將原先的陣列內容複製過來,再丟棄舊的陣列。因此,對於較大物件的擴容會涉及大量的記憶體複製操作,如果能夠預先評估大小,可提升效能。

唯一需要注意的是:StringBuffer是執行緒安全的,但是StringBuilder是執行緒不安全的。可參看Java標準類庫的原始碼,StringBuffer類中方法定義前面都會有synchronize關鍵字。為此,StringBuffer的效能要遠低於StringBuilder。


3 應用場景

[A]在字串內容不經常發生變化的業務場景優先使用String類。例如:常量宣告、少量的字串拼接操作等。如果有大量的字串內容拼接,避免使用String與String之間的“+”操作,因為這樣會產生大量無用的中間物件,耗費空間且執行效率低下(新建物件、回收物件花費大量時間)。

[B]在頻繁進行字串的運算(如拼接、替換、刪除等),並且執行在多執行緒環境下,建議使用StringBuffer,例如XML解析、HTTP引數解析與封裝。

[C]在頻繁進行字串的運算(如拼接、替換、刪除等),並且執行在單執行緒環境下,建議使用StringBuilder,例如SQL語句拼裝、JSON封裝等。