你說你精通spring源碼?那你知道StringBuffer的擴(kuò)容原理是什么嗎

前言

在Java中掠械,String是一個(gè)常量由缆,一旦創(chuàng)建其值后不能更改但可以共享。

如果我們把多個(gè)字符串進(jìn)行連接(拼接)操作猾蒂,就會(huì)開辟很多空間均唉,從而造成了大量內(nèi)存空間的浪費(fèi)。

為了解決這個(gè)問題肚菠,我們需要用到StringBuffer類和StringBuilder類浸卦。

這兩個(gè)類可牛逼了,它們都是可變長度的字符串類案糙,在字符串的拼接處理上大大提高了效率限嫌。

一、StringBuffer與StringBuilder的區(qū)別

共同點(diǎn):底層數(shù)據(jù)結(jié)構(gòu)都是char類型的數(shù)組时捌,都是可變的字符串怒医。

不同點(diǎn):StringBuffer線程同步的安全性高,但多線程操作時(shí)效率低奢讨。StringBuilder線程不同步稚叹,進(jìn)行多線程操作時(shí),安全性低,但效率高扒袖。

因?yàn)檫@兩個(gè)類的用法都類似塞茅,所以我就以StringBuffer類為例來講解。

二季率、StringBuffer類的定義

StringBuffer類的部分源碼:

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

從源碼中可以看出野瘦,StringBuffer是一個(gè)用final修飾的最終類,繼承了父類AbstractStringBuilder類飒泻,實(shí)現(xiàn)了Serializable接口和CharSequence接口鞭光,說明具備了兩種能力。

三泞遗、四個(gè)構(gòu)造方法

StringBuffer類的部分源碼:

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

重點(diǎn)講下這兩個(gè)構(gòu)造方法:

構(gòu)造方法:StringBuffer()

方法描述:構(gòu)造一個(gè)沒有字符的字符串緩沖區(qū)惰许,初始容量為16。

構(gòu)造方法:StringBuffer(String str)

方法描述:構(gòu)造一個(gè)初始化為指定字符串內(nèi)容的字符串緩沖區(qū)史辙,初始容量為str.length() + 16汹买。

實(shí)例:

package cn.tkr.demo;

public class MyStringBuffer {
    public static void main(String[] args) {
        
        StringBuffer sb1 = new StringBuffer();
        System.out.println("sb1字符緩沖區(qū)的容量:" + sb1.capacity()); //獲取當(dāng)前StringBuffer的容量

        StringBuffer sb2 = new StringBuffer("LoveJava");
        System.out.println("sb2字符緩沖區(qū)的容量:" + sb2.capacity()); //獲取當(dāng)前StringBuffer的容量
    }
}

運(yùn)行結(jié)果:

sb1字符緩沖區(qū)的容量:16
sb2字符緩沖區(qū)的容量:24

實(shí)例分析:調(diào)用無參數(shù)構(gòu)造函數(shù),sb1字符緩沖區(qū)的初始容量為16聊倔,調(diào)用有參數(shù)構(gòu)造函數(shù)晦毙,初始容量為字符串的長度(8) + 16,所以初始容量為24方库。

四结序、StringBuffer的常用方法

注: append(...)中的...代表各種類型的參數(shù),如append(int i)纵潦、append(char c)徐鹤、append(String str)等

五、StringBuffer的擴(kuò)容原理

擴(kuò)容原理:

StringBuffer的底層數(shù)組結(jié)構(gòu)用的是char類型的數(shù)組邀层。

所以返敬,當(dāng)我們使用StringBuffer對象的append(...)方法追加數(shù)據(jù)時(shí),如果char類型數(shù)組的長度無法容納我們追加的數(shù)據(jù)寥院,StringBuffer就會(huì)進(jìn)行擴(kuò)容劲赠。

擴(kuò)容時(shí)會(huì)用到Arrays類中的copyOf(...)方法,每次擴(kuò)容的容量大小是原來的容量的2倍加2秸谢。

注: copyOf(...)中的...代表各種類型的參數(shù)凛澎,如
copyOf(int[] original, int newLength)、copyOf(char[] original, int newLength)等

實(shí)例源碼分析:

假設(shè)我現(xiàn)在調(diào)用了append(String str)方法估蹄,追加了一個(gè)字符串(char類型數(shù)組的長度無法容納的字符串)塑煎。

append(String str)方法源碼:

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

方法中通過super.append(str)調(diào)用了父類的append(String str)方法。

父類的append(String str)方法源碼:

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

重點(diǎn)來了臭蚁,這里的ensureCapacityInternal(count + len)就是一個(gè)擴(kuò)容相關(guān)的方法最铁,變量count是一個(gè)全局變量讯赏,并沒有實(shí)際的值,變量len是我們追加進(jìn)來的字符串的長度冷尉。

也就是說漱挎,我們追加進(jìn)來的字符串的長度會(huì)傳遞給ensureCapacityInternal(int minimumCapacity)方法。

再來看看ensureCapacityInternal(int minimumCapacity)方法的源碼:

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

其中雀哨,minimumCapacity指我們追加進(jìn)來的字符串的長度磕谅,value是一個(gè)全局的char類型的數(shù)組名。

也就說震束,value.length指數(shù)組的長度怜庸,那如果(minimumCapacity - value.length > 0)這個(gè)條件成立当犯,也就意味著垢村,char類型數(shù)組的長度無法容納我們追加的字符串的長度。

這時(shí)嚎卫,就需要使用Arrays類中的copyOf(char[] original, int newLength)方法進(jìn)行擴(kuò)容嘉栓。

方法:

copyOf(char[] original, int newLength)

描述:復(fù)制指定的數(shù)組,截?cái)嗷蚴褂孟鄳?yīng)的默認(rèn)值進(jìn)行填充

該方法的第一個(gè)參數(shù)是源數(shù)組名拓诸,所以要傳遞的是value侵佃。

第二個(gè)參數(shù)是新數(shù)組長度,新數(shù)組長度的值是通過newCapacity(int minCapacity)方法來計(jì)算并返回的值奠支。

newCapacity(int minCapacity)方法的源碼:

private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }

這個(gè)方法會(huì)返回一個(gè)新的容量大胁霰病(即新數(shù)組長度),每次擴(kuò)容的容量大小是原來的容量的2倍加2倍谜。

六迈螟、最后

感謝你看到這里,說的都是自己的一些看法和見解尔崔,如有不對答毫,請指正!覺得文章對你有幫助的話不妨給我點(diǎn)個(gè)贊季春,每天都會(huì)分享java相關(guān)技術(shù)文章或行業(yè)資訊洗搂,歡迎大家關(guān)注和轉(zhuǎn)發(fā)文章!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末载弄,一起剝皮案震驚了整個(gè)濱河市耘拇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宇攻,老刑警劉巖惫叛,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尺碰,居然都是意外死亡挣棕,警方通過查閱死者的電腦和手機(jī)译隘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洛心,“玉大人固耘,你說我怎么就攤上這事〈噬恚” “怎么了厅目?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長法严。 經(jīng)常有香客問我损敷,道長,這世上最難降的妖魔是什么深啤? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任拗馒,我火速辦了婚禮,結(jié)果婚禮上溯街,老公的妹妹穿的比我還像新娘诱桂。我一直安慰自己,他們只是感情好呈昔,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布挥等。 她就那樣靜靜地躺著,像睡著了一般堤尾。 火紅的嫁衣襯著肌膚如雪肝劲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天郭宝,我揣著相機(jī)與錄音辞槐,去河邊找鬼。 笑死剩蟀,一個(gè)胖子當(dāng)著我的面吹牛催蝗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播育特,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼丙号,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了缰冤?” 一聲冷哼從身側(cè)響起犬缨,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎棉浸,沒想到半個(gè)月后怀薛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡迷郑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年枝恋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了创倔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡焚碌,死狀恐怖畦攘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情十电,我是刑警寧澤知押,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站鹃骂,受9級特大地震影響台盯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜畏线,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一静盅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧象踊,春花似錦温亲、人聲如沸棚壁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽袖外。三九已至史隆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間曼验,已是汗流浹背泌射。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鬓照,地道東北人熔酷。 一個(gè)月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像豺裆,于是被迫代替她去往敵國和親拒秘。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359