String、StringBuffer、StringBuilder區別

1、String、StringBuffer、StringBuilder區別html

1.可變與不可變
(1). String類中使用字符數組保存字符串,由於有「final」修飾符,因此string對象是不可變的。segmentfault

private final char value[];

(2). StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數組保存字符串,這兩種對象都是可變的。數組

char[] value; //char數組的初始長度爲16

2.是否多線程安全
(1). String中的對象是不可變的,也就能夠理解爲常量,顯然線程安全。(這裏的不可變能夠理解成:String類型對象自己是不可變的)
線程安全能夠理解爲共享變量值是安全的,而String用final修飾,會被存儲到一個叫作常量池的內存區域。安全

但什麼又會以爲String是能夠被修改的,那麼String的線程安全是怎麼來的呢多線程

String a="test";
a="test1"

這裏a就變成了test1,其實在這裏是新建了一個"test1"字符串對象(若是常量池沒有這個值的話就是新建)。而後將變量引用指向它。注意:這裏並無修改"test"這個變量的內部狀態,"test"這個字符串對象是線程安全的。app

(2). StringBuilder是非線程安全的
StringBuffer對方法加了同步鎖或者對調用的方法加了同步鎖,因此是線程安全的。ide

    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    @Override
    public synchronized StringBuffer reverse() {
        toStringCache = null;
        super.reverse();
        return this;
    }

    @Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

2、StringBuffer、StringBuilder的相同點:
StringBuilder與StringBuffer有公共父類AbstractStringBuilder(抽象類)。優化

抽象類與接口的其中一個區別是:抽象類中能夠定義一些子類的公共方法,子類只須要增長新的功能,不須要重複寫已經存在的方法;而接口中只是對方法的申明和常量的定義。
StringBuilder、StringBuffer的方法都會調用AbstractStringBuilder中的公共方法,如super.append(...)、super.delete(...)、super.reverse()等。只是StringBuffer會在方法上加synchronized關鍵字,進行同步。ui

關於append方法:
使用append方法添加字符串的過程
(1). 先檢查內部char[]數組是否須要擴容
(2). 如須要擴容則進行擴容,而後將原來元數據copy到新數組中。 (由於從新分配內存並拷貝的開銷比較大,因此每次從新申請內存空間都是採用申請大於當前須要的內存空間的方式,這裏是2倍。)
(3). 再將新添加的元數據加入到新char[]數組中this

參考:
https://blog.csdn.net/sinat_36705710/article/details/64440820
https://segmentfault.com/q/1010000007763710

速度
StringBuilder > StringBuffer > String (string要每次建立一個新對象)
可是在鏈接字符串的時候,String+的速度大於StringBuilder、StringBuffer,由於String+在編譯期間作了優化
例:

String str = "a" + "bc"; //對於String+的賦值語句,在編譯期間,直接將String賦值爲abc

但如有成百上千個的鏈接字符串,把String+語句拆分紅for循環語句時,String+的速度小於StringBuilder、StringBuffer,由於String會每次循環就建立一個新對象
參考:http://www.javashuo.com/article/p-pggmqgsd-gz.html

相關文章
相關標籤/搜索