對象性能 | String | StringBuffer(線程安全) | StringBuilder(非線程安全) |
---|---|---|---|
性能比例 | 50000 | 5 | 4 |
繼承 | 無 | AbstractStringBuilder | AbstractStringBuilder(會拋錯誤) |
變量差異
private transient char[] toStringCache;
StringBuffer擁有變量toStringCache,其限定詞transient表不做序列化。
方法差異
StringBuffer比StringBuilder多一個synchronized,詳見synchronized原理。
StringBuffer append(String str)
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
StringBuilder append(String str)
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
StringBuffer reverse()
@Override
public synchronized StringBuffer reverse() {
toStringCache = null;
super.reverse();
return this;
}
StringBuilder reverse()
@Override
public StringBuilder reverse() {
super.reverse();
return this;
}
StringBuffer的toString方法與StringBuilder的toString方法有一點區別。這裏是通過toStringCache成員構造String對象然後返回的。因爲這裏創建String對象調用的是String類的String(char[] value, boolean share)構造方法,是共享字符數組的,以提高效率不清楚的同學可以看下之前的String源碼。所以設計者通過toStringCache來保證每次調用toString方法時得到的String對象是不變所結果。試想一下如果沒有使用toStringCache,而是直接共享了value,那麼在調用toString方法後,再對StringBuffer進行操作的時候之前返回的String對象就改變了,違背了String對象不變的設計理念。
對於其它的方法都是調用父類的方法實現,但都加上了synchronized來保證線程安全的效果。這裏拿一個函數舉例說明。其它的方法實現看其父類AbstractStringBuilder實現.(摘:https://www.jianshu.com/p/6a713cad80a9)
StringBuffer toString()
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
StringBuilder toString()
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
在進行序列化(將內存的對象放到文件裏)的時候保存StringBuilder對象的狀態到一個流中。詳見java.io.ObjectOutputStream。二者差異及場景未明。
StringBuffer writeObject(java.io.ObjectOutputStream s)
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();
}
StringBuilder writeObject(java.io.ObjectOutputStream s)
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
s.defaultWriteObject();
s.writeInt(count);
s.writeObject(value);
}
StringBuffer serialPersistentFields
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),
};