面試——StringBuffer源碼淺析(大致結構和append方法)

原文鏈接:https://my.oschina.net/91jason/blog/304514

java的StringBuffer是通過char[]數組實現的。只有當調用stringbuffer的tostring方法纔會轉換成string對象。

char[]數組有個初始化的值,其初始化長度未16.如果不夠則繼續申請更多的空間,申請更多的空間用的是arraycopy方法。

StringBuffer類繼承自 AbstractStringBuilder 抽象類,實現Serializable序列化接口和CharSequence接口。

AbstractStringBuilder抽象類實現Appendabel,CharSequence接口。

另外,StringBuilder的源碼跟StringBuffer類似,看完Buffer再看Builder,找出不同點看看就大致可以。

一,關於append方法淺析。

append方法都做了同步聲明,其中源碼如下

public synchronized StringBuffer append(String str) {
	super.append(str);
        return this;
}

1、StringBuffer的方法都加了synchronized關鍵字,線程安全。

2、synchronized代表方法加鎖,例如線程A,要運行到聲明瞭synchronized 方法時,先檢查有沒有其他線程B,C正在使用這synchronized 方法,若有就先等B,C線程運行完這個synchronized 方法後,在運行A,若無直接運行,

3、synchronized兩種用法:synchronized方法和synchronized塊。

synchronized(syncObject) {  // synchronized代碼塊
  //允許訪問控制的代碼
}

4、圍觀append源碼

     第一步:StringBuffer類體內

 

/*

 *  可見是通過super調用父類AbstractStringBuilder中定義的append方法。
 */
public synchronized StringBuffer append(StringBuffer sb) {
        super.append(sb);
        return this;
}

    第二步:AbstractStringBuilder抽象類體內

 

/**
 *  AbstractStringBuilder屬性有:
 *          char value[];  // The value is used for character storage(). 容量
 *          int count;  // The count is the number of characters used.實際字符數
 */
public AbstractStringBuilder append(StringBuffer sb) {
	if (sb == null)
            return append("null");
	int len = sb.length();
	int newCount = count + len;  
	if (newCount > value.length)
	    expandCapacity(newCount); // 若value存儲容量不夠需擴容。擴容方法省略暫不分析,基本上根據Arrays.copyOf()方法,複製指定的數組,以使副本具有指定的長度。到頭來copyOf的源碼一樣是利用arraycopy方法來複制數組和擴容
	sb.getChars(0, len, value, count); // 把sb的內容0->len複製到value中,注意value參數,此時的value是已經擴容後的value。
	count = newCount;  // 更新新count值
	return this;
}

    原有count要加上len(len也就是新增的count)成newCount,若這newCount總數要大於原有value的容量,就要     擴容纔可以容納newCount個字符。再用getChars複製數組。

    第三步:AbstractStringBuilder裏定義的getChars方法體,是對System.arraycopy方法 + 邊界檢查的進一步封裝                 而已。

public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) //  dstBegin就是原有count接下來的位置
    {
	if (srcBegin < 0)
	    throw new StringIndexOutOfBoundsException(srcBegin);
	if ((srcEnd < 0) || (srcEnd > count))
	    throw new StringIndexOutOfBoundsException(srcEnd);
        if (srcBegin > srcEnd)
            throw new StringIndexOutOfBoundsException("srcBegin > srcEnd"); //以上是Bound Check
	System.arraycopy(value, srcBegin,dst, dstBegin, srcEnd - srcBegin);  // 從指定源數組中複製一個數組
}

arraycopy方法參數

  • src - 源數組。
  • srcPos - 源數組中的起始位置。

  • dest - 目標數組。

  • destPos - 目標數據中的起始位置。

  • length - 要複製的數組元素的數量。 

注意value和dst

這個value是sb.value,srcEnd-srcBegin個元素全部複製dst(也就是擴容的value)中。(這裏我理解正確嗎?)

 

待續...

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