作者: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
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));
}
}
字符串的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;
}
假設(shè)執(zhí)行如下代碼:
StringBuffer sb = new StringBuffer("abghij");
sb.insert(2, "cdef");
字符串的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類
為什么是線程安全的
線程安全是指多線程操作同一個(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)鍵字