String、StringBuffer與StringBuilder的區別,及實現原理

原文鏈接:https://blog.csdn.net/m_Tenderness/article/details/90758848

源碼分析
String使用final關鍵字修飾可以知道String是不可變的類,String中字符數組的長度你定義多少,就是多少,不存在字符數組擴容一說。內部是final修飾的char[] value,表示String類不可被繼承,且value只能被初始化一次。這裏的value變量其實就是存儲了String字符串中的所有字符。
StringBuffer和StringBuilder二者的源碼以及append方法,二者都是AbstractStringBuilder的子類,也都實現了Serializable(可序列化)和CharSequence(char類型的可讀序列)接口,AbstractStringBuilder 實現了Appendable(長度可增加)和CharSequence接口。

//String
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
        /** The value is used for character storage. */
    private final char value[];
    public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }
}
//StringBuilder
public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence{
    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
}
    
//StringBuffer
 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence{
    @Override
    private transient char[] toStringCache;
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
}

//AbstractStringBuilder 
abstract class AbstractStringBuilder implements Appendable, CharSequence{
	char[] value;
	int count;
	AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }
}

String中單的subString方法在最後會使用new關鍵字創建一個新的對象,如果傳入0也是new一個新的和原來相同長度相同內容的字符串返回。其他對字符串的操作方法也是創建一個新的String對象返回
StringBuffer上使用了synchronized 關鍵字加了同步鎖證明它是線程安全的,而StringBuilder沒有使用說明是線程不安全的

StringBuilder原理分析
內部調用父類的構造方法,內部是容量爲16的字符數組。
StringBuilder的構造方法、append()和toString()方法

public StringBuilder(int capacity) {
        super(capacity);
    }
        public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }
     public StringBuilder(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }
        @Override
    public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
      @Override
    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

在參數String類型的構造方法中,在本身字符串長度的基礎上再增加16個字符長度,作爲StringBuilder實例的初始數組容量,並將str字符串 append到StringBuilder的數組中。
這裏的toString方法直接new 一個String對象,將StringBuilder對象的value進行一個拷貝,重新生成一個對象,不直接操作StringBuilder的value。
StringBuilder沒有像String一樣去重新new 對象,所以在頻繁的拼接字符上省去了new 關鍵字的StringBuilder,不必每次都要重新開闢新的內存空間,其效率遠遠高於String類。

StringBuffer原理分析
StringBuffer是線程安全的高效字符串操作類,在StringBuilder上加了鎖機制
StringBuilder的構造方法、append()和toString()方法

public StringBuffer() {
        super(16);
    }
    public StringBuffer(int capacity) {
        super(capacity);
    }
     public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }
     public StringBuffer(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }
     @Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }
    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
     public synchronized StringBuffer append(StringBuffer sb) {
        toStringCache = null;
        super.append(sb);
        return this;
    }
     @Override
    synchronized StringBuffer append(AbstractStringBuilder asb) {
        toStringCache = null;
        super.append(asb);
        return this;
    }
     @Override
    public synchronized StringBuffer append(CharSequence s) {
        toStringCache = null;
        super.append(s);
        return this;
    }
     @Override
    public synchronized StringBuffer append(CharSequence s, int start, int end)
    {
        toStringCache = null;
        super.append(s, start, end);
        return this;
    }

    @Override
    public synchronized StringBuffer append(char[] str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public synchronized StringBuffer append(char[] str, int offset, int len) {
        toStringCache = null;
        super.append(str, offset, len);
        return this;
    }
	@Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

StringBuffer比StringBuilder多了一個toStringCache域,用以去除toString方法的緩存
作用就是如果StringBuffer對象此時存在toStringCache,在多次調用其toString方法時,其new出來的String對象是會共享同一個char[] 內存的,達到共享的目的。但是StringBuffer只要做了修改,其toStringCache屬性值都會置null處理。

總結
String 類不可變,內部維護的char[] 數組長度不可變,爲final修飾,String類也是final修飾,不存在擴容。字符串拼接,截取,都會生成一個新的對象。頻繁操作字符串效率低下,因爲每次都會生成新的對象。
StringBuilder 類內部維護可變長度char[] , 初始化數組容量爲16,存在擴容, 其append拼接字符串方法內部調用System的native方法,進行數組的拷貝,不會重新生成新的StringBuilder對象。
它是非線程安全的字符串操作類, 其每次調用 toString方法而重新生成的String對象,不會共享StringBuilder對象內部的char[],會進行一次char[]的copy操作。
StringBuffer 類內部維護可變長度char[], 基本上與StringBuilder一致,但其爲線程安全的字符串操作類,大部分方法都採用了Synchronized關鍵字修改,以此來實現在多線程下的操作字符串的安全性。
其toString方法而重新生成的String對象,會共享StringBuffer對象中的toStringCache屬性(char[]),但是每次的StringBuffer對象修改,都會置null該屬性值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章