今天很你們來聊一下這個基礎的問題java
說他們三者之間的區別我總結爲一下三點:數組
下面我來一個一個解釋:安全
廢話很少說,先上源碼!app
若是你能夠打開三個類的源碼看一下你就明白了性能
咱們能看到,String這個類底層使用了final修飾的長度不可變的字符數組,因此它長度不可變ui
private final char value[];
而StringBuffer和StringBuilder 都繼承自AbstractStringBuilder ,且AbstractStringBuilder底層使用的是可變字符數組,因此兩者長度可變。spa
char[] value;
先來看這樣一段代碼線程
public class MainTest { public static void main(String[] args) { String str = "abc"; System.out.println(str); str = str + "cd"; System.out.println(str); } }
輸出結果爲:abccode
abcd對象
整個程序運行完咱們看似是str這個對象被更改了,在後面加上了一段新的字符,但這只是假象,由於咱們剛纔說過String類型的字符串長度是不可變的啊,其實JVM是先建立的了一個str對象,將「abc」賦值給str,而後在內存中又建立了第二個str對象,將第一個str對象中的「abc」與」de「相加再賦值給第二個str對象,此時Java虛擬機的垃圾回收機制開始其工做將第一個str對象回收。因此說String類型的字符串要完成這樣」改變長度「的操做須要不斷地建立再回收,建立再回收,無形中通過了不少步驟,而 StringBuffer和SringBuilder數組可變,直接可進行更改,因此要更快。
而SringBuilder 爲何比 StringBuffer 要快呢?
先來看源碼:
從圖中能夠看出StringBuffer的append的方法都被toStringCache關鍵字修飾了(不止圖中這兩個append方法包括StringBuffer源碼中全部append重載方法都被toStringCache修飾了。)
toStringCache關鍵字是給線程加鎖,枷鎖是會帶來性能上的損耗的,故用SringBuilder 比 StringBuffer 要快
鎖不懂先不要緊,往下看!暫且理解爲何快。
線程安全不一樣的問題要和剛纔的的思路連起來,正是由於有了toStringCache關鍵字修飾StringBuffer的append方法有,給線程加了鎖加了鎖因此線程安全。
這樣理解,若是一個StringBuffer對象的字符串在字符串緩衝區被多個線程同時使用時,也就是多個線程同時操做,這樣會有出現錯誤操做的機率,爲了保證線程的安全性,進行加鎖,這樣會使同一時間只有一個線程得到權限,其餘線程必須等待該線程結束並釋放鎖才能得到權限,這樣線程很是安全,雖然效率慢了點,可是當項目安全性要求很高時就必須用StringBuffer。單一線程下仍是的用更快一點的SringBuilder 。