StringBuffer類原碼解析

StringBuffer類用於字符串的拼接,由於它動態改變字符數組的長度並且事先會留有冗餘長度,而不是像String拼接一樣不斷的重新創建新的String對象,所以速度上StringBuffer是快過String類的

從StringBuffer源碼可以看到它是繼承了AbstractStringBuilder類的,這個類暫時先不管他,我們主要看一下StringBuffer類的append方法

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

我們主要看參數爲String類型的append方法,其餘重載方法要麼調用該方法要麼也與其實現方式大同小異

先不管這個toStringCache參數,字面意思上可以大概知道該參數是用來做緩存的,我們從這個方法進入到其父類AbstarctStringBuilder的append方法中

public AbstractStringBuilder append(String str) {
        //第一步進行非空判斷
        if (str == null)
            return appendNull();
        int len = str.length();
        //第二步進行字符數組長度適應
        ensureCapacityInternal(count + len);
        //第三步進行字符內容正式遷移
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

先看第一步,這裏調用了appendNull方法,看看這個方法

    private AbstractStringBuilder appendNull() {
        int c = count;
        ensureCapacityInternal(c + 4);
        final char[] value = this.value;
        value[c++] = 'n';
        value[c++] = 'u';
        value[c++] = 'l';
        value[c++] = 'l';
        count = c;
        return this;
    }

這個方法實際上就是拼接了“null”字符串,回到第二步,看實現字符數組長度適應的ensureCapacityInternal方法

private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

這個方法傳入了一個最小長度,如果當前字符數組長度不夠,便調用Arrays.copyOf方法改變value長度,看看這個方法

public static char[] copyOf(char[] original, int newLength) {
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

這個copyOf方法中創建了一個新的字符數組,並用arraycopy方法將原來數組的內容存了進行

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
代碼解釋:
  Object src : 原數組
   int srcPos : 從元數據的起始位置開始
  Object dest : 目標數組
  int destPos : 目標數組的開始起始位置
  int length  : 要copy的數組的長度   

將src數組從srcPos位置開始,複製長度爲length的內容到dest數組,起始位置爲destPos

 回到ensureCapacityInternal方法,可以看到它讓value重新指向了這個新創建的字符數組從而實現了數組長度的變化

private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

 在看append方法的第三部,調用了String.getChars方法進行內容的拼接,而getChars在一系列校驗之後最終是調用native層的getCharsNoCheck方法,

native void getCharsNoCheck(int start, int end, char[] buffer, int index) 
代碼解釋:   
    int start : 起始位置 
    int end : 終止位置   
    char[] buffer : 目標數組   
    int index : 目標數組的開始起始位置  

將該字符串從start到end的內容複製到buffer數組,起始位置爲index

 於是再看AbstractStringBuilder.append方法,便一目瞭然,最後改變一下當前的字符內容長度並返回

public AbstractStringBuilder append(String str) {
        //第一步進行非空判斷
        if (str == null)
            return appendNull();
        int len = str.length();
        //第二步進行字符數組長度適應
        ensureCapacityInternal(count + len);
        //第三步進行字符內容正式遷移
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章