淺析我對(duì) String、StringBuilder、StringBuffer 的理解
StringBuilder、StringBuffer 和 String 一樣,都是用于存儲(chǔ)字符串的。
1、那既然有了 String ,為什么還需要他們兩個(gè)呢?
原因是 String 是不可變的,它每次的字符串拼接,實(shí)際上都會(huì) new 一個(gè)新的 String 進(jìn)行接收。
2、談?wù)凷tringBuilder、StringBuffer他們兩個(gè)的聯(lián)系:
我們可以知道 StringBuffer 在 1.0 的時(shí)候就發(fā)布了,那為什么還需要 StringBuilder 呢?原因是它的大部分方法都上了鎖,是線程安全的,導(dǎo)致了效率較低!而我們有時(shí)候不需要考慮線程安全問(wèn)題,追求效率!所以 StringBuilder 在 1.5 的時(shí)候就出來(lái)了!
3、StringBuilder、StringBuffer 的異同:*
不同:
- StringBuffer 它因?yàn)樽非蟀踩?,給大量方法上鎖,線程安全!
- StringBuilder 它因?yàn)樽非笮?,沒(méi)有給方法上鎖,線程不安全!
相同:內(nèi)部方法和 StringBuffer 完全一致,因?yàn)槎祭^承了 AbstractStringBuilder,底層數(shù)組都是用父類的。
4、源碼淺析 String:
結(jié)論:final 修飾了底層的字符數(shù)組,故內(nèi)容不可變。
5、源碼淺析 StringBuilder:構(gòu)造方法
觀察構(gòu)造方法:
public StringBuilder() { super(16); } public StringBuilder(int capacity) { super(capacity); } public StringBuilder(String str) { super(str.length() + 16); append(str); } public StringBuilder(CharSequence seq) { this(seq.length() + 16); append(seq); }
結(jié)論:可以看出,它有一個(gè)默認(rèn)的長(zhǎng)度 16!而當(dāng)傳入?yún)?shù)是一個(gè)字符或者字符串時(shí),它也會(huì)自動(dòng)的傳入?yún)?shù)的長(zhǎng)度上加上 16!
6、源碼淺析 StringBuilder:append 方法
@Override public StringBuilder append(Object obj) { return append(String.valueOf(obj)); } @Override public StringBuilder append(String str) { super.append(str); return this; }
我們發(fā)現(xiàn),它還是調(diào)用的父類的 append 方法,說(shuō)明這個(gè)方法他并沒(méi)有重寫,那么 StringBuffer 也一樣!
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; }
結(jié)論:我們可以看出,他也是可以拼接 null 的!
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; }
然后觀察,它接著進(jìn)行了一個(gè)數(shù)組容量的判斷,而數(shù)組的擴(kuò)容,其實(shí)就是在里面實(shí)現(xiàn)的,我們點(diǎn)進(jìn)去看一下!
private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity)); } }
結(jié)論:它先是判斷,當(dāng)前數(shù)組容量+拼接字符 是否大于 數(shù)組長(zhǎng)度,如果大于,則進(jìn)行數(shù)組拷貝,并將底層數(shù)組的引用指向新數(shù)組!
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; }
結(jié)論:由此可見(jiàn),新數(shù)組長(zhǎng)度擴(kuò)容為原數(shù)組的 2倍+2 !
問(wèn)題:那它究竟是怎么拼接字符串的呢?
sb.getChars(0, len, value, count);
進(jìn)去看一下:String 的 getChars 方法
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { if (srcBegin < 0) throw new StringIndexOutOfBoundsException(srcBegin); if ((srcEnd < 0) || (srcEnd > count)) throw new StringIndexOutOfBoundsException(srcEnd); if (srcBegin > srcEnd) throw new StringIndexOutOfBoundsException("srcBegin > srcEnd"); System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); }
實(shí)際調(diào)用了一個(gè)系統(tǒng)類方法:arraycopy,再點(diǎn)進(jìn)去看一下!
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
結(jié)論:底層最終是調(diào)用的本地方法,實(shí)現(xiàn)了的字符數(shù)組拷貝,但由于本地方法是可以和操作系統(tǒng)直接打交道的,所以它的 append 字符串拼接效率會(huì)高于 String!
總結(jié)
到此這篇關(guān)于淺析我對(duì) String、StringBuilder、StringBuffer 的理解的文章就介紹到這了,更多相關(guān) String、StringBuilder、StringBuffer 的理解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java基于jdbc實(shí)現(xiàn)簡(jiǎn)單學(xué)生管理系統(tǒng)
本文主要主要介紹了java連接mysql數(shù)據(jù)庫(kù)的一個(gè)簡(jiǎn)單學(xué)生系統(tǒng),通過(guò)jdbc連接數(shù)據(jù)庫(kù)。文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10Springboot指定掃描路徑的實(shí)現(xiàn)示例
本文主要介紹了Springboot指定掃描路徑的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05基于mybatis中<include>標(biāo)簽的作用說(shuō)明
這篇文章主要介紹了基于mybatis中<include>標(biāo)簽的作用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02利用Java多線程技術(shù)導(dǎo)入數(shù)據(jù)到Elasticsearch的方法步驟
這篇文章主要介紹了利用Java多線程技術(shù)導(dǎo)入數(shù)據(jù)到Elasticsearch的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Struts 2中實(shí)現(xiàn)Ajax的三種方式
這篇文章主要介紹了Struts 2中實(shí)現(xiàn)Ajax的三種方式,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05