Java源碼系列 -- StringBuffer

一、類簽名

相信看過(guò) Java源碼系列(2) -- StringBuilder 的讀者都了解StringBuilderStringBuffer的異同,這里我們?cè)購(gòu)?fù)習(xí)一次加深印象。

public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

StringBuilderStringBuffer同樣繼承自AbstractStringBuilder父類,字符串序列增刪查改等主要操作均在父類中實(shí)現(xiàn)。StringBuilder調(diào)用父類方法的時(shí)候,不會(huì)對(duì)正在進(jìn)行的操作進(jìn)行同步處理,而StringBuffer相反。一個(gè)同步鎖的差異能影響多線程修改字符串序列的行為方式和線程處理過(guò)程中的性能。除此之外,他們倆都支持序列化。

二、數(shù)據(jù)成員

// 當(dāng)字符串被修改之后,值最新緩存會(huì)被toString返回
private transient char[] toStringCache;
static final long serialVersionUID = 3388685877147921107L;

三、構(gòu)造方法

默認(rèn)創(chuàng)建長(zhǎng)度為16的字符串序列,也可以自定義字符串序列長(zhǎng)度。若用一個(gè)字符串為構(gòu)造參數(shù)的話,構(gòu)造方法會(huì)在原字符串上再加上16的緩沖長(zhǎng)度。

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);
}

四、成員方法

為了保證線程安全,幾乎所有方法都使用synchronized修飾符。同步鎖加在這個(gè)字符串序列實(shí)例上,只要有一個(gè)線程已經(jīng)占用這個(gè)實(shí)例,其他線程只能等待上一個(gè)線程釋放同步鎖再去競(jìng)爭(zhēng)。

值得一提的是,synchronied鎖有三種類別,分別是對(duì)象鎖、實(shí)例鎖類鎖。對(duì)象鎖是類中有一個(gè)靜態(tài)常量Object對(duì)象作代碼塊鎖的鎖對(duì)象,只要同步代碼塊已經(jīng)持有該對(duì)象,其他同步代碼塊只能等待上一個(gè)鎖釋放;實(shí)例鎖的實(shí)例方法使用synchronied作為鎖目標(biāo),只要該實(shí)例有一個(gè)同步方法在使用,其他線程對(duì)同一個(gè)實(shí)例同步操作只能等待上一個(gè)同步結(jié)束;類鎖針對(duì)類靜態(tài)方法需要使用線程同步的情況。由于靜態(tài)類不需要初始化構(gòu)造就能被訪問(wèn),所以需要上鎖的地方只能把整個(gè)類作為鎖目標(biāo)。

4.1 序列長(zhǎng)

@Override
public synchronized int length() {
    return count;
}

@Override
public synchronized int capacity() {
    return value.length;
}

@Override
public synchronized void ensureCapacity(int minimumCapacity) {
    if (minimumCapacity > value.length) {
        expandCapacity(minimumCapacity);
    }
}

@Override
public synchronized void trimToSize() {
    super.trimToSize();
}

@Override
public synchronized void setLength(int newLength) {
    toStringCache = null;
    super.setLength(newLength);
}

4.2 查找

@Override
public synchronized char charAt(int index) {
    if ((index < 0) || (index >= count))
        throw new StringIndexOutOfBoundsException(index);
    return value[index];
}

@Override
public synchronized int codePointAt(int index) {
    return super.codePointAt(index);
}

@Override
public synchronized int codePointBefore(int index) {
    return super.codePointBefore(index);
}

@Override
public synchronized int codePointCount(int beginIndex, int endIndex) {
    return super.codePointCount(beginIndex, endIndex);
}

@Override
public synchronized int offsetByCodePoints(int index, int codePointOffset) {
    return super.offsetByCodePoints(index, codePointOffset);
}

@Override
public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
                                  int dstBegin)
{
    super.getChars(srcBegin, srcEnd, dst, dstBegin);
}

@Override
public int indexOf(String str) {
    // 備注:這個(gè)方法的同步依賴于其他StringBuffer方法的實(shí)現(xiàn)
    return super.indexOf(str);
}

@Override
public synchronized int indexOf(String str, int fromIndex) {
    return super.indexOf(str, fromIndex);
}

@Override
public int lastIndexOf(String str) {
    // 備注:這個(gè)方法的同步依賴于其他StringBuffer方法的實(shí)現(xiàn)
    return lastIndexOf(str, count);
}

@Override
public synchronized int lastIndexOf(String str, int fromIndex) {
    return super.lastIndexOf(str, fromIndex);
}

4.3 追加

@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;
}

/**
 * Appends the specified {@code StringBuffer} to this sequence.
 * <p>
 * The characters of the {@code StringBuffer} argument are appended,
 * in order, to the contents of this {@code StringBuffer}, increasing the
 * length of this {@code StringBuffer} by the length of the argument.
 * If {@code sb} is {@code null}, then the four characters
 * {@code "null"} are appended to this {@code StringBuffer}.
 * <p>
 * Let <i>n</i> be the length of the old character sequence, the one
 * contained in the {@code StringBuffer} just prior to execution of the
 * {@code append} method. Then the character at index <i>k</i> in
 * the new character sequence is equal to the character at index <i>k</i>
 * in the old character sequence, if <i>k</i> is less than <i>n</i>;
 * otherwise, it is equal to the character at index <i>k-n</i> in the
 * argument {@code sb}.
 * <p>
 * This method synchronizes on {@code this}, the destination
 * object, but does not synchronize on the source ({@code sb}).
 *
 * @param   sb   the {@code StringBuffer} to append.
 * @return  a reference to this object.
 * @since 1.4
 */
public synchronized StringBuffer append(StringBuffer sb) {
    toStringCache = null;
    super.append(sb);
    return this;
}

/**
 * @since 1.8
 */
@Override
synchronized StringBuffer append(AbstractStringBuilder asb) {
    toStringCache = null;
    super.append(asb);
    return this;
}

/**
 * Appends the specified {@code CharSequence} to this
 * sequence.
 * <p>
 * The characters of the {@code CharSequence} argument are appended,
 * in order, increasing the length of this sequence by the length of the
 * argument.
 *
 * <p>The result of this method is exactly the same as if it were an
 * invocation of this.append(s, 0, s.length());
 *
 * <p>This method synchronizes on {@code this}, the destination
 * object, but does not synchronize on the source ({@code s}).
 *
 * <p>If {@code s} is {@code null}, then the four characters
 * {@code "null"} are appended.
 *
 * @param   s the {@code CharSequence} to append.
 * @return  a reference to this object.
 * @since 1.5
 */
@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;
}

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

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

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

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

@Override
public synchronized StringBuffer appendCodePoint(int codePoint) {
    toStringCache = null;
    super.appendCodePoint(codePoint);
    return this;
}

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

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

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

4.4 替換

@Override
public synchronized StringBuffer replace(int start, int end, String str) {
    toStringCache = null;
    super.replace(start, end, str);
    return this;
}

@Override
public synchronized void setCharAt(int index, char ch) {
    if ((index < 0) || (index >= count))
        throw new StringIndexOutOfBoundsException(index);
    toStringCache = null;
    value[index] = ch;
}

4.5 子序列

@Override
public synchronized String substring(int start) {
    return substring(start, count);
}

@Override
public synchronized CharSequence subSequence(int start, int end) {
    return super.substring(start, end);
}

@Override
public synchronized String substring(int start, int end) {
    return super.substring(start, end);
}

4.6 插入

@Override
public synchronized StringBuffer insert(int index, char[] str, int offset,
                                        int len)
{
    toStringCache = null;
    super.insert(index, str, offset, len);
    return this;
}

@Override
public synchronized StringBuffer insert(int offset, Object obj) {
    toStringCache = null;
    super.insert(offset, String.valueOf(obj));
    return this;
}

@Override
public synchronized StringBuffer insert(int offset, String str) {
    toStringCache = null;
    super.insert(offset, str);
    return this;
}

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


@Override
public StringBuffer insert(int dstOffset, CharSequence s) {
    // Note, synchronization achieved via invocations of other StringBuffer methods
    // after narrowing of s to specific type
    // Ditto for toStringCache clearing
    super.insert(dstOffset, s);
    return this;
}

@Override
public synchronized StringBuffer insert(int dstOffset, CharSequence s,
        int start, int end)
{
    toStringCache = null;
    super.insert(dstOffset, s, start, end);
    return this;
}

@Override
public  StringBuffer insert(int offset, boolean b) {
    // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
    // after conversion of b to String by super class method
    // Ditto for toStringCache clearing
    super.insert(offset, b);
    return this;
}

@Override
public synchronized StringBuffer insert(int offset, char c) {
    toStringCache = null;
    super.insert(offset, c);
    return this;
}

@Override
public StringBuffer insert(int offset, int i) {
    // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
    // after conversion of i to String by super class method
    // Ditto for toStringCache clearing
    super.insert(offset, i);
    return this;
}

@Override
public StringBuffer insert(int offset, long l) {
    // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
    // after conversion of l to String by super class method
    // Ditto for toStringCache clearing
    super.insert(offset, l);
    return this;
}

@Override
public StringBuffer insert(int offset, float f) {
    // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
    // after conversion of f to String by super class method
    // Ditto for toStringCache clearing
    super.insert(offset, f);
    return this;
}

@Override
public StringBuffer insert(int offset, double d) {
    // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
    // after conversion of d to String by super class method
    // Ditto for toStringCache clearing
    super.insert(offset, d);
    return this;
}

4.7 翻轉(zhuǎn)

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

4.8 刪除

@Override
public synchronized StringBuffer delete(int start, int end) {
    toStringCache = null;
    super.delete(start, end);
    return this;
}

@Override
public synchronized StringBuffer deleteCharAt(int index) {
    toStringCache = null;
    super.deleteCharAt(index);
    return this;
}

4.9 toString

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

五、序列化

private static final java.io.ObjectStreamField[] serialPersistentFields =
{
    new java.io.ObjectStreamField("value", char[].class),
    new java.io.ObjectStreamField("count", Integer.TYPE),
    new java.io.ObjectStreamField("shared", Boolean.TYPE),
};

private synchronized void writeObject(java.io.ObjectOutputStream s)
    throws java.io.IOException {
    java.io.ObjectOutputStream.PutField fields = s.putFields();
    fields.put("value", value);
    fields.put("count", count);
    fields.put("shared", false);
    s.writeFields();
}

private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException {
    java.io.ObjectInputStream.GetField fields = s.readFields();
    value = (char[])fields.get("value", null);
    count = fields.get("count", 0);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,734評(píng)論 18 399
  • (一)Java部分 1、列舉出JAVA中6個(gè)比較常用的包【天威誠(chéng)信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,265評(píng)論 0 62
  • 今天閨女比較乖,一向周末不午睡的她,在我的“威逼利誘”下睡到現(xiàn)在還沒(méi)醒。日語(yǔ)學(xué)習(xí)任務(wù)基本完成,提前來(lái)更文。 單詞及...
    諾凡閱讀 438評(píng)論 0 5
  • 憂憂把晨讀寫成自己的成長(zhǎng)感悟。 “這件事你說(shuō)我自己知道答案?怎么可能?我要是知道答案我干嘛還要來(lái)問(wèn)你?扯淡!” “...
    Mjinxiu無(wú)憂閱讀 1,521評(píng)論 3 10
  • 我們每天都會(huì)遇到大大小小的各種事情需要去決定,家庭中的,工作中的等等,決定成為我們生活中一件非常重要的事,尤其是重...
    常知了了閱讀 385評(píng)論 0 0

友情鏈接更多精彩內(nèi)容