Java StringBuffer和StringBuilder

作者:ouyangyewei
個(gè)人站點(diǎn):http://ouyangyewei.me/


簡(jiǎn)介

StringBuffer和StringBuilder,兩者都是可變對(duì)象,都繼承java.lang.AbstractStringBuilder類盔粹,都實(shí)現(xiàn)java.io.Serializable和java.lang.CharSequence接口妖碉。
最大的區(qū)別在于:<b><u>StringBuffer是線程安全的,而StringBuilder是非線程安全的</u></b>

下面代碼摘自java.lang.StringBuffer

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

下面代碼摘自java.lang.StringBuilder

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

AbstractStringBuilder類

AbstractStringBuilder類封裝了StringBuffer和StringBuilder大部分操作的實(shí)現(xiàn)。

字符串的內(nèi)存形態(tài)

下面代碼摘自java.lang.AbstractStringBuilder

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     */
    char[] value;

    /**
     * The count is the number of characters used.
     */
    int count;

StringBuffer和StringBuilder沒(méi)有具體的成員變量來(lái)存儲(chǔ)字符串懊缺,而是使用繼承自AbstractStringBuilder類的成員變量char[] value信姓,因?yàn)闆](méi)有使用final關(guān)鍵字修飾,因此值是可變的张弛。

字符串構(gòu)造方法

下面代碼摘自java.lang.StringBuffer

public StringBuffer() {
    super(16);
}

下面代碼摘自java.lang.StringBuilder

public StringBuilder() {
    super(16);
}

下面代碼摘自java.lang.AbstractStringBuilder

AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}

當(dāng)創(chuàng)建一個(gè)StirngBuffer或StringBuilder對(duì)象時(shí)荒典,若不指定容量,則默認(rèn)創(chuàng)建長(zhǎng)度為16的char類型數(shù)組

字符串的append操作

下面代碼摘自java.lang.AbstractStringBuilder吞鸭,以入?yún)镾tring對(duì)象為例

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    // 檢查是否char[]數(shù)組是否需要擴(kuò)容
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}

private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    // value.length默認(rèn)長(zhǎng)度是16
    // minimumCapacity = str.length + 字符串的實(shí)際長(zhǎng)度
    // 若當(dāng)前字符串?dāng)?shù)組長(zhǎng)度不足最小應(yīng)分配的長(zhǎng)度寺董,則將重新創(chuàng)建一個(gè)長(zhǎng)度的char[]數(shù)組
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}
StringBuffer.append()
StringBuffer.append()

字符串的insert操作

下面代碼摘自java.lang.AbstractStringBuilder,以入?yún)镾tring對(duì)象為例

public AbstractStringBuilder insert(int offset, String str) {
    if ((offset < 0) || (offset > length()))
        throw new StringIndexOutOfBoundsException(offset);
    if (str == null)
        str = "null";
    int len = str.length();
    ensureCapacityInternal(count + len);
    System.arraycopy(value, offset, value, offset + len, count - offset);
    str.getChars(value, offset);
    count += len;
    return this;
}
StringBuffer.insert
StringBuffer.insert

假設(shè)執(zhí)行如下代碼:

StringBuffer sb = new StringBuffer("abghij");
sb.insert(2, "cdef");
StringBuffer.insert.visio
StringBuffer.insert.visio

字符串的delete操作

下面代碼摘自java.lang.AbstractStringBuilder

public AbstractStringBuilder delete(int start, int end) {
    if (start < 0)
        throw new StringIndexOutOfBoundsException(start);
    if (end > count)
        end = count;
    if (start > end)
        throw new StringIndexOutOfBoundsException();
    int len = end - start;
    if (len > 0) {
        System.arraycopy(value, start+len, value, start, count-end);
        count -= len;
    }
    return this;
}

實(shí)際上的操作是字符串?dāng)?shù)組拷貝刻剥,假設(shè)執(zhí)行如下代碼:

StringBuffer sb = new StringBuffer("abcdefghij");
sb.delete(2, 6);
StringBuffer.delete
StringBuffer.delete

StringBuffer類

為什么是線程安全的

線程安全是指多線程操作同一個(gè)對(duì)象遮咖,不會(huì)出現(xiàn)同步等問(wèn)題。StringBuffer類中透敌,使用了大量的synchronized關(guān)鍵字來(lái)修飾方法盯滚。
摘取java.lang.StringBuffer部分使用synchronized關(guān)鍵字修飾的代碼

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

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

@Override
public synchronized void ensureCapacity(int minimumCapacity) {
    super.ensureCapacity(minimumCapacity);
}

transient關(guān)鍵字

摘自Java Language Specification, Java SE 7 Edition, Section 8.3.1.3. transient Fields

Variables may be marked transient to indicate that they are not part of the persistent state of an object.

在Java中,transient關(guān)鍵字用來(lái)指出哪些成員變量不應(yīng)該被序列化酗电。值得注意的是:

  • 序列化針對(duì)的是對(duì)象魄藕,而不是類;
  • static修飾的變量撵术,本身是隱式的transient背率,同時(shí)靜態(tài)變量是屬于類層次,不能被序列化嫩与;
  • transient只能用于修飾成員變量寝姿,不能修飾本地變量,不能修飾方法和類划滋。

StringBuffer類中饵筑,有一個(gè)成員變量

/**
 * A cache of the last value returned by toString. Cleared
 * whenever the StringBuffer is modified.
 */
private transient char[] toStringCache;

toStringCache這個(gè)成員變量,從命名上看处坪,猜測(cè)是為了用于toString()方法而做的字符串緩沖根资。可見(jiàn)同窘,如果是為了做緩沖玄帕,確實(shí)沒(méi)必要在StringBuffer對(duì)象中持久化。

toString的操作

下面代碼摘自java.lang.StringBuffer

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

toStringCache獲得實(shí)際長(zhǎng)度的字符串?dāng)?shù)組想邦,并創(chuàng)建一個(gè)String對(duì)象


參考材料

Java SE java.lang.StringBuffer
Java SE java.lang.StringBuilder
Java transient關(guān)鍵字

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末裤纹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子丧没,更是在濱河造成了極大的恐慌鹰椒,老刑警劉巖锡移,帶你破解...
    沈念sama閱讀 212,686評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異吹零,居然都是意外死亡罩抗,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)灿椅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)套蒂,“玉大人,你說(shuō)我怎么就攤上這事茫蛹〔俚叮” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,160評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵婴洼,是天一觀的道長(zhǎng)骨坑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)柬采,這世上最難降的妖魔是什么欢唾? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,736評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮粉捻,結(jié)果婚禮上礁遣,老公的妹妹穿的比我還像新娘。我一直安慰自己肩刃,他們只是感情好祟霍,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,847評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著盈包,像睡著了一般沸呐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呢燥,一...
    開(kāi)封第一講書(shū)人閱讀 50,043評(píng)論 1 291
  • 那天崭添,我揣著相機(jī)與錄音,去河邊找鬼叛氨。 笑死滥朱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的力试。 我是一名探鬼主播,決...
    沈念sama閱讀 39,129評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼排嫌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼畸裳!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起淳地,我...
    開(kāi)封第一講書(shū)人閱讀 37,872評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤怖糊,失蹤者是張志新(化名)和其女友劉穎帅容,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體伍伤,經(jīng)...
    沈念sama閱讀 44,318評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡并徘,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,645評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扰魂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片麦乞。...
    茶點(diǎn)故事閱讀 38,777評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖劝评,靈堂內(nèi)的尸體忽然破棺而出姐直,到底是詐尸還是另有隱情,我是刑警寧澤蒋畜,帶...
    沈念sama閱讀 34,470評(píng)論 4 333
  • 正文 年R本政府宣布声畏,位于F島的核電站,受9級(jí)特大地震影響姻成,放射性物質(zhì)發(fā)生泄漏插龄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,126評(píng)論 3 317
  • 文/蒙蒙 一科展、第九天 我趴在偏房一處隱蔽的房頂上張望均牢。 院中可真熱鬧,春花似錦辛润、人聲如沸膨处。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,861評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)真椿。三九已至,卻和暖如春乎澄,著一層夾襖步出監(jiān)牢的瞬間突硝,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,095評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工置济, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留解恰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,589評(píng)論 2 362
  • 正文 我出身青樓浙于,卻偏偏與公主長(zhǎng)得像护盈,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子羞酗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,687評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法腐宋,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法胸竞,異常的語(yǔ)法欺嗤,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,602評(píng)論 18 399
  • 當(dāng)字符串進(jìn)行修改的時(shí)候,需要用到StringBuffer和StringBuilder類卫枝。和String類不同的是煎饼,...
    wuchaooooo閱讀 169評(píng)論 0 0
  • 1. ArrayList、LinkedList校赤、Vector的區(qū)別 答: 相同點(diǎn): ArraList吆玖、Linked...
    wayneinyz閱讀 214評(píng)論 0 0
  • struct RegexHelper { let regex : NSRegularExpression init...
    fordring2008閱讀 411評(píng)論 0 0
  • 這里以鼠標(biāo)左擊,即mouseDown為例痒谴。 我們通常的做法是衰伯,實(shí)現(xiàn)一個(gè)NSView的子類,例如mac微信中的MMV...
    悲觀患者閱讀 1,971評(píng)論 0 1