一、類簽名
相信看過(guò) Java源碼系列(2) -- StringBuilder 的讀者都了解StringBuilder和StringBuffer的異同,這里我們?cè)購(gòu)?fù)習(xí)一次加深印象。
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
StringBuilder和StringBuffer同樣繼承自AbstractStringBuilder父類,字符串序列增刪查改等主要操作均在父類中實(shí)現(xiàn)。StringBuilder調(diào)用父類方法的時(shí)候,不會(huì)對(duì)正在進(jìn)行的操作進(jìn)行同步處理,而StringBuffer相反。一個(gè)同步鎖的差異能影響多線程修改字符串序列的行為方式和線程處理過(guò)程中的性能。除此之外,他們倆都支持序列化。
二、數(shù)據(jù)成員
// 當(dāng)字符串被修改之后,值最新緩存會(huì)被toString返回
private transient char[] toStringCache;
static final long serialVersionUID = 3388685877147921107L;
三、構(gòu)造方法
默認(rèn)創(chuàng)建長(zhǎng)度為16的字符串序列,也可以自定義字符串序列長(zhǎng)度。若用一個(gè)字符串為構(gòu)造參數(shù)的話,構(gòu)造方法會(huì)在原字符串上再加上16的緩沖長(zhǎng)度。
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);
}
四、成員方法
為了保證線程安全,幾乎所有方法都使用synchronized修飾符。同步鎖加在這個(gè)字符串序列實(shí)例上,只要有一個(gè)線程已經(jīng)占用這個(gè)實(shí)例,其他線程只能等待上一個(gè)線程釋放同步鎖再去競(jìng)爭(zhēng)。
值得一提的是,synchronied鎖有三種類別,分別是對(duì)象鎖、實(shí)例鎖、類鎖。對(duì)象鎖是類中有一個(gè)靜態(tài)常量Object對(duì)象作代碼塊鎖的鎖對(duì)象,只要同步代碼塊已經(jīng)持有該對(duì)象,其他同步代碼塊只能等待上一個(gè)鎖釋放;實(shí)例鎖的實(shí)例方法使用synchronied作為鎖目標(biāo),只要該實(shí)例有一個(gè)同步方法在使用,其他線程對(duì)同一個(gè)實(shí)例同步操作只能等待上一個(gè)同步結(jié)束;類鎖針對(duì)類靜態(tài)方法需要使用線程同步的情況。由于靜態(tài)類不需要初始化構(gòu)造就能被訪問(wèn),所以需要上鎖的地方只能把整個(gè)類作為鎖目標(biāo)。
4.1 序列長(zhǎng)
@Override
public synchronized int length() {
return count;
}
@Override
public synchronized int capacity() {
return value.length;
}
@Override
public synchronized void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > value.length) {
expandCapacity(minimumCapacity);
}
}
@Override
public synchronized void trimToSize() {
super.trimToSize();
}
@Override
public synchronized void setLength(int newLength) {
toStringCache = null;
super.setLength(newLength);
}
4.2 查找
@Override
public synchronized char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}
@Override
public synchronized int codePointAt(int index) {
return super.codePointAt(index);
}
@Override
public synchronized int codePointBefore(int index) {
return super.codePointBefore(index);
}
@Override
public synchronized int codePointCount(int beginIndex, int endIndex) {
return super.codePointCount(beginIndex, endIndex);
}
@Override
public synchronized int offsetByCodePoints(int index, int codePointOffset) {
return super.offsetByCodePoints(index, codePointOffset);
}
@Override
public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
int dstBegin)
{
super.getChars(srcBegin, srcEnd, dst, dstBegin);
}
@Override
public int indexOf(String str) {
// 備注:這個(gè)方法的同步依賴于其他StringBuffer方法的實(shí)現(xiàn)
return super.indexOf(str);
}
@Override
public synchronized int indexOf(String str, int fromIndex) {
return super.indexOf(str, fromIndex);
}
@Override
public int lastIndexOf(String str) {
// 備注:這個(gè)方法的同步依賴于其他StringBuffer方法的實(shí)現(xiàn)
return lastIndexOf(str, count);
}
@Override
public synchronized int lastIndexOf(String str, int fromIndex) {
return super.lastIndexOf(str, fromIndex);
}
4.3 追加
@Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
}
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
/**
* Appends the specified {@code StringBuffer} to this sequence.
* <p>
* The characters of the {@code StringBuffer} argument are appended,
* in order, to the contents of this {@code StringBuffer}, increasing the
* length of this {@code StringBuffer} by the length of the argument.
* If {@code sb} is {@code null}, then the four characters
* {@code "null"} are appended to this {@code StringBuffer}.
* <p>
* Let <i>n</i> be the length of the old character sequence, the one
* contained in the {@code StringBuffer} just prior to execution of the
* {@code append} method. Then the character at index <i>k</i> in
* the new character sequence is equal to the character at index <i>k</i>
* in the old character sequence, if <i>k</i> is less than <i>n</i>;
* otherwise, it is equal to the character at index <i>k-n</i> in the
* argument {@code sb}.
* <p>
* This method synchronizes on {@code this}, the destination
* object, but does not synchronize on the source ({@code sb}).
*
* @param sb the {@code StringBuffer} to append.
* @return a reference to this object.
* @since 1.4
*/
public synchronized StringBuffer append(StringBuffer sb) {
toStringCache = null;
super.append(sb);
return this;
}
/**
* @since 1.8
*/
@Override
synchronized StringBuffer append(AbstractStringBuilder asb) {
toStringCache = null;
super.append(asb);
return this;
}
/**
* Appends the specified {@code CharSequence} to this
* sequence.
* <p>
* The characters of the {@code CharSequence} argument are appended,
* in order, increasing the length of this sequence by the length of the
* argument.
*
* <p>The result of this method is exactly the same as if it were an
* invocation of this.append(s, 0, s.length());
*
* <p>This method synchronizes on {@code this}, the destination
* object, but does not synchronize on the source ({@code s}).
*
* <p>If {@code s} is {@code null}, then the four characters
* {@code "null"} are appended.
*
* @param s the {@code CharSequence} to append.
* @return a reference to this object.
* @since 1.5
*/
@Override
public synchronized StringBuffer append(CharSequence s) {
toStringCache = null;
super.append(s);
return this;
}
@Override
public synchronized StringBuffer append(CharSequence s, int start, int end)
{
toStringCache = null;
super.append(s, start, end);
return this;
}
@Override
public synchronized StringBuffer append(char[] str) {
toStringCache = null;
super.append(str);
return this;
}
@Override
public synchronized StringBuffer append(char[] str, int offset, int len) {
toStringCache = null;
super.append(str, offset, len);
return this;
}
@Override
public synchronized StringBuffer append(boolean b) {
toStringCache = null;
super.append(b);
return this;
}
@Override
public synchronized StringBuffer append(char c) {
toStringCache = null;
super.append(c);
return this;
}
@Override
public synchronized StringBuffer append(int i) {
toStringCache = null;
super.append(i);
return this;
}
@Override
public synchronized StringBuffer appendCodePoint(int codePoint) {
toStringCache = null;
super.appendCodePoint(codePoint);
return this;
}
@Override
public synchronized StringBuffer append(long lng) {
toStringCache = null;
super.append(lng);
return this;
}
@Override
public synchronized StringBuffer append(float f) {
toStringCache = null;
super.append(f);
return this;
}
@Override
public synchronized StringBuffer append(double d) {
toStringCache = null;
super.append(d);
return this;
}
4.4 替換
@Override
public synchronized StringBuffer replace(int start, int end, String str) {
toStringCache = null;
super.replace(start, end, str);
return this;
}
@Override
public synchronized void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
toStringCache = null;
value[index] = ch;
}
4.5 子序列
@Override
public synchronized String substring(int start) {
return substring(start, count);
}
@Override
public synchronized CharSequence subSequence(int start, int end) {
return super.substring(start, end);
}
@Override
public synchronized String substring(int start, int end) {
return super.substring(start, end);
}
4.6 插入
@Override
public synchronized StringBuffer insert(int index, char[] str, int offset,
int len)
{
toStringCache = null;
super.insert(index, str, offset, len);
return this;
}
@Override
public synchronized StringBuffer insert(int offset, Object obj) {
toStringCache = null;
super.insert(offset, String.valueOf(obj));
return this;
}
@Override
public synchronized StringBuffer insert(int offset, String str) {
toStringCache = null;
super.insert(offset, str);
return this;
}
@Override
public synchronized StringBuffer insert(int offset, char[] str) {
toStringCache = null;
super.insert(offset, str);
return this;
}
@Override
public StringBuffer insert(int dstOffset, CharSequence s) {
// Note, synchronization achieved via invocations of other StringBuffer methods
// after narrowing of s to specific type
// Ditto for toStringCache clearing
super.insert(dstOffset, s);
return this;
}
@Override
public synchronized StringBuffer insert(int dstOffset, CharSequence s,
int start, int end)
{
toStringCache = null;
super.insert(dstOffset, s, start, end);
return this;
}
@Override
public StringBuffer insert(int offset, boolean b) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of b to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, b);
return this;
}
@Override
public synchronized StringBuffer insert(int offset, char c) {
toStringCache = null;
super.insert(offset, c);
return this;
}
@Override
public StringBuffer insert(int offset, int i) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of i to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, i);
return this;
}
@Override
public StringBuffer insert(int offset, long l) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of l to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, l);
return this;
}
@Override
public StringBuffer insert(int offset, float f) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of f to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, f);
return this;
}
@Override
public StringBuffer insert(int offset, double d) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of d to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, d);
return this;
}
4.7 翻轉(zhuǎn)
@Override
public synchronized StringBuffer reverse() {
toStringCache = null;
super.reverse();
return this;
}
4.8 刪除
@Override
public synchronized StringBuffer delete(int start, int end) {
toStringCache = null;
super.delete(start, end);
return this;
}
@Override
public synchronized StringBuffer deleteCharAt(int index) {
toStringCache = null;
super.deleteCharAt(index);
return this;
}
4.9 toString
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
五、序列化
private static final java.io.ObjectStreamField[] serialPersistentFields =
{
new java.io.ObjectStreamField("value", char[].class),
new java.io.ObjectStreamField("count", Integer.TYPE),
new java.io.ObjectStreamField("shared", Boolean.TYPE),
};
private synchronized void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
java.io.ObjectOutputStream.PutField fields = s.putFields();
fields.put("value", value);
fields.put("count", count);
fields.put("shared", false);
s.writeFields();
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
java.io.ObjectInputStream.GetField fields = s.readFields();
value = (char[])fields.get("value", null);
count = fields.get("count", 0);
}