StringBuffer 是 Java 1.0 就存在的線程安全可變字串建構器。本文基於 JDK 1.6/1.8 原始碼,深度剖析其類別結構、同步機制、擴容策略、核心方法實現,並與 StringBuilder、AbstractStringBuilder 關係圖解說明。
java.lang.Object
└── java.lang.AbstractStringBuilder (包私有,核心邏輯)
├── java.lang.StringBuffer (final, synchronized)
└── java.lang.StringBuilder (final, 非同步)
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
final:不可被繼承Serializable、CharSequenceAbstractStringBuilder
// 幾乎所有公共方法皆加 synchronized
public synchronized int length() { return count; }
public synchronized int capacity() { return value.length; }
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
public synchronized StringBuffer insert(int index, char[] str, int offset, int len) {
toStringCache = null;
super.insert(index, str, offset, len);
return this;
}
public synchronized StringBuffer delete(int start, int end) {
toStringCache = null;
super.delete(start, end);
return this;
}
public synchronized String toString() {
// 複製字元陣列確保不可變快照
return new String(value, 0, count);
}
// 1. 無參:預設容量 16
public StringBuffer() {
super(16);
}
// 2. 指定初始容量
public StringBuffer(int capacity) {
super(capacity);
}
// 3. 從字串初始化:容量 = 字串長度 + 16
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
// 4. 從 CharSequence 初始化 (JDK 5+)
public StringBuffer(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer();
System.out.println(s1.capacity()); // 16
StringBuffer s2 = new StringBuffer(100);
System.out.println(s2.capacity()); // 100
StringBuffer s3 = new StringBuffer("abc");
System.out.println(s3.capacity()); // 19 (3+16)
System.out.println(s3); // abc
}
所有實質字元操作 (append、insert、delete、reverse 等) 均委派給 AbstractStringBuilder:
public StringBuffer append(String str) {
toStringCache = null; // 使 toString 快取失效
super.append(str); // 父類實際處理
return this; // 支援鏈式呼叫
}
private transient char[] toStringCache; // 不序列化
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOf(value, count); // 複製快照
}
return new String(toStringCache);
}
toStringCache = null 失效
private void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity < 0) { // 溢位處理
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}
新容量 = 舊容量 * 2 + 2
// AbstractStringBuilder.append(String)
public AbstractStringBuilder append(String str) {
if (str == null) str = "null";
int len = str.length();
ensureCapacityInternal(count + len); // 擴容檢查
str.getChars(0, len, value, count); // 字元複製
count += len;
return this;
}
public AbstractStringBuilder insert(int index, String str) {
if (index < 0 || index > count) throw new StringIndexOutOfBoundsException();
if (str == null) str = "null";
int len = str.length();
ensureCapacityInternal(count + len);
// 後段元素右移
System.arraycopy(value, index, value, index + len, count - index);
// 插入新字元
str.getChars(0, len, value, index);
count += len;
return this;
}
public AbstractStringBuilder delete(int start, int end) {
if (start < 0) start = 0;
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;
}
public AbstractStringBuilder reverse() {
boolean hasSurrogate = false;
int n = count - 1;
for (int j = (n - 1) >> 1; j >= 0; j--) {
char temp = value[j];
char temp2 = value[n - j];
if (!hasSurrogate) {
// 處理代理對 (Supplementary Characters)
if (Character.isLowSurrogate(temp) || Character.isHighSurrogate(temp2)) {
hasSurrogate = true;
}
}
value[j] = temp2;
value[n - j] = temp;
}
if (hasSurrogate) {
// 修正代理對順序
for (int j = 0; j < count; j++) {
char c = value[j];
if (Character.isHighSurrogate(c)) {
// 交換高低代理位置
}
}
}
return this;
}
| 維度 | String | StringBuilder | StringBuffer |
|---|---|---|---|
| 可變性 | 不可變 | 可變 | 可變 |
| 線程安全 | 天然安全 | 不安全 | 方法級同步 |
| 效能 | 拼接慢 | 最快 | 次快 |
| 繼承 | final | final | final |
| JDK 版本 | 1.0 | 5.0 | 1.0 |
| toString | 自身 | 新建 String | 快取 + 新建 |
| 適用場景 | 常量、參數 | 單線程建構 | 多線程共享建構 |
StringBuilder (預設)、ThreadLocal (高併發復用)StringBuffer 或 Collections.synchronizedList() 包裝 StringBuilderStringJoiner (Java 8) 或 String.format()CharArrayWriter / ByteArrayOutputStream 避免字元編碼開銷StringBuffer 以方法級同步實現線程安全,核心邏輯委派給 AbstractStringBuilder,擴容策略為 2n+2,toString 採用快取機制。現代開發 95% 場景應優先選用 StringBuilder,僅在確定多線程共享同一建構器實例時使用 StringBuffer。理解其原始碼結構有助於排查併發問題、優化字串操作效能。