淺析我對 String、StringBuilder、StringBuffer 的理解
StringBuilder、StringBuffer 和 String 一樣,都是用于存儲字符串的。
1、那既然有了 String ,為什么還需要他們兩個呢?
原因是 String 是不可變的,它每次的字符串拼接,實際上都會 new 一個新的 String 進行接收。
2、談?wù)凷tringBuilder、StringBuffer他們兩個的聯(lián)系:
我們可以知道 StringBuffer 在 1.0 的時候就發(fā)布了,那為什么還需要 StringBuilder 呢?原因是它的大部分方法都上了鎖,是線程安全的,導(dǎo)致了效率較低!而我們有時候不需要考慮線程安全問題,追求效率!所以 StringBuilder 在 1.5 的時候就出來了!
3、StringBuilder、StringBuffer 的異同:*
不同:
- StringBuffer 它因為追求安全,給大量方法上鎖,線程安全!
- StringBuilder 它因為追求效率,沒有給方法上鎖,線程不安全!
相同:內(nèi)部方法和 StringBuffer 完全一致,因為都繼承了 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é)論:可以看出,它有一個默認的長度 16!而當(dāng)傳入?yún)?shù)是一個字符或者字符串時,它也會自動的傳入?yún)?shù)的長度上加上 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 方法,說明這個方法他并沒有重寫,那么 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;
}
然后觀察,它接著進行了一個數(shù)組容量的判斷,而數(shù)組的擴容,其實就是在里面實現(xià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ù)組長度,如果大于,則進行數(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é)論:由此可見,新數(shù)組長度擴容為原數(shù)組的 2倍+2 !
問題:那它究竟是怎么拼接字符串的呢?
sb.getChars(0, len, value, count);
進去看一下: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);
}
實際調(diào)用了一個系統(tǒng)類方法:arraycopy,再點進去看一下!
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
結(jié)論:底層最終是調(diào)用的本地方法,實現(xiàn)了的字符數(shù)組拷貝,但由于本地方法是可以和操作系統(tǒng)直接打交道的,所以它的 append 字符串拼接效率會高于 String!
總結(jié)
到此這篇關(guān)于淺析我對 String、StringBuilder、StringBuffer 的理解的文章就介紹到這了,更多相關(guān) String、StringBuilder、StringBuffer 的理解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java基于jdbc實現(xiàn)簡單學(xué)生管理系統(tǒng)
本文主要主要介紹了java連接mysql數(shù)據(jù)庫的一個簡單學(xué)生系統(tǒng),通過jdbc連接數(shù)據(jù)庫。文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10
基于mybatis中<include>標(biāo)簽的作用說明
這篇文章主要介紹了基于mybatis中<include>標(biāo)簽的作用說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02
利用Java多線程技術(shù)導(dǎo)入數(shù)據(jù)到Elasticsearch的方法步驟
這篇文章主要介紹了利用Java多線程技術(shù)導(dǎo)入數(shù)據(jù)到Elasticsearch的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07

