对象性能 | 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),
};