Java StringBuilder和StringBuffer源碼分析
StringBuilder與StringBuffer是兩個常用的操作字符串的類。大家都知道,StringBuilder是線程不安全的,而StringBuffer是線程安全的。前者是JDK1.5加入的,后者在JDK1.0就有了。下面分析一下它們的內(nèi)部實現(xiàn)。
一、繼承關(guān)系
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
可以看到,兩個類的繼承關(guān)系是一模一樣的。Serializable是可以序列化的標(biāo)志。CharSequence接口包含了charAt()、length() 、subSequence()、toString()這幾個方法,String類也實現(xiàn)了這個接口。這里的重點是抽象類AbstractStringBuilder,這個類封裝了StringBuilder和StringBuffer大部分操作的實現(xiàn)。
二、AbstractStringBuilder
1、變量及構(gòu)造方法
char[] value;
int count;
AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
AbstractStringBuilder內(nèi)部用一個char[]數(shù)組保存字符串,可以在構(gòu)造的時候指定初始容量方法。
2、擴(kuò)容
public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > 0)
ensureCapacityInternal(minimumCapacity);
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);
}
擴(kuò)容的方法最終是由expandCapacity()實現(xiàn)的,在這個方法中首先把容量擴(kuò)大為原來的容量加2,如果此時仍小于指定的容量,那么就把新的容量設(shè)為minimumCapacity。然后判斷是否溢出,如果溢出了,把容量設(shè)為Integer.MAX_VALUE。最后把value值進(jìn)行拷貝,這顯然是耗時操作。
3、append()方法
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;
}
append()是最常用的方法,它有很多形式的重載。上面是其中一種,用于追加字符串。如果str是null,則會調(diào)用appendNull()方法。這個方法其實是追加了'n'、'u'、'l'、'l'這幾個字符。如果不是null,則首先擴(kuò)容,然后調(diào)用String的getChars()方法將str追加到value末尾。最后返回對象本身,所以append()可以連續(xù)調(diào)用。
三、StringBuilder
AbstractStringBuilder已經(jīng)實現(xiàn)了大部分需要的方法,StringBuilder和StringBuffer只需要調(diào)用即可。下面來看看StringBuilder的實現(xiàn)。
1、構(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);
}
可以看出,StringBuilder默認(rèn)的容量大小為16。當(dāng)然也可以指定初始容量,或者以一個已有的字符序列給StringBuilder對象賦初始值。
2、append()方法
public StringBuilder append(String str) {
super.append(str);
return this;
}
public StringBuilder append(CharSequence s) {
super.append(s);
return this;
}
append()的重載方法很多,這里隨便列舉了兩個。顯然,這里是直接調(diào)用的父類AbstractStringBuilder中的方法。
3、toString()
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
toString()方法返回了一個新的String對象,與原來的對象不共享內(nèi)存。其實AbstractStringBuilder中的subString()方法也是如此。
四、SringBuffer
StiringBuffer跟StringBuilder類似,只不過為了實現(xiàn)同步,很多方法使用lSynchronized修飾,如下面的方法:
public synchronized int length() {
return count;
}
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
public synchronized void setLength(int newLength) {
toStringCache = null;
super.setLength(newLength);
}
可以看到,方法前面確實加了Synchronized。
另外,在上面的append()以及setLength()方法里面還有個變量toStringCache。這個變量是用于最近一次toString()方法的緩存,任何時候只要StringBuffer被修改了這個變量會被賦值為null。StringBuffer的toString如下:
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
在這個方法中,如果toStringCache為null則先緩存。最終返回的String對象有點不同,這個構(gòu)造方法還有個參數(shù)true。找到String的源碼看一下:
String(char[] value, boolean share) {
// assert share : "unshared not supported";
this.value = value;
}
原來這個構(gòu)造方法構(gòu)造出來的String對象并沒有實際復(fù)制字符串,只是把value指向了構(gòu)造參數(shù),這是為了節(jié)省復(fù)制元素的時間。不過這個構(gòu)造器是具有包訪問權(quán)限,一般情況下是不能調(diào)用的。
總結(jié)
- StringBuilder和StringBuffer都是可變字符串,前者線程不安全,后者線程安全。
- StringBuilder和StringBuffer的大部分方法均調(diào)用父類AbstractStringBuilder的實現(xiàn)。其擴(kuò)容機(jī)制首先是把容量變?yōu)樵瓉砣萘康?倍加2。最大容量是Integer.MAX_VALUE,也就是0x7fffffff。
- StringBuilder和StringBuffer的默認(rèn)容量都是16,最好預(yù)先估計好字符串的大小避免擴(kuò)容帶來的時間消耗。
以上就是本文的全部內(nèi)容,希望對大家學(xué)習(xí)Java中兩個常用的操作字符串的類StringBuilder和StringBuffer有所幫助。
- Java詳細(xì)分析String類與StringBuffer和StringBuilder的使用方法
- java中String StringBuffer和StringBuilder的區(qū)別詳解
- java中String、StringBuffer與StringBuilder的區(qū)別
- 兩萬字詳解Java Sring String的常見操作以及StringBuffer StringBuilder的區(qū)別
- JAVA基礎(chǔ)類庫之String類,StringBuffer類和StringBuilder類
- Java中關(guān)于String StringBuffer StringBuilder特性深度解析
- 詳解java中String、StringBuilder、StringBuffer的區(qū)別
- java String、StringBuilder和StringBuffer的區(qū)別詳解
- Java源碼深度分析String與StringBuffer及StringBuilder詳解
相關(guān)文章
maven package 打包報錯 Failed to execute goal的解決
這篇文章主要介紹了maven package 打包報錯 Failed to execute goal的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
MyBatis測試報錯:Cannot?determine?value?type?from?string?&a
這篇文章主要給大家介紹了關(guān)于MyBatis測試報錯:Cannot?determine?value?type?from?string?'xxx'的解決辦法,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02
Java?Web實現(xiàn)簡易圖書管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java?Web實現(xiàn)簡易圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-09-09

