Comparison of StringBuffer and StringBuilder
- Variable difference
- Method differences
- StringBuffer append(String str)
- StringBuilder append(String str)
- StringBuffer reverse()
- StringBuilder reverse()
- StringBuffer toString()
- StringBuilder toString()
- StringBuffer writeObject(java.io.ObjectOutputStream s)
- StringBuilder writeObject(java.io.ObjectOutputStream s)
- StringBuffer serialPersistentFields
Object performance | String | StringBuffer (thread safe) | StringBuilder (non-thread safe) |
---|---|---|---|
Performance ratio | 50000 | 5 | 4 |
inherit | no | AbstractStringBuilder | AbstractStringBuilder (will throw an error) |
Variable difference
private transient char[] toStringCache;
StringBuffer has the variable toStringCache, and its qualifier transient table is not serialized.
Method differences
StringBuffer has one more synchronized than StringBuilder, see the principle of synchronized for details.
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;
}
The toString method of StringBuffer is slightly different from the toString method of StringBuilder. Here is a String object constructed by the toStringCache member and then returned. Because the String object created here calls the String (char [] value, boolean share) constructor of the String class, which is a shared character array, to improve efficiency. Students who are not clear can see the previous String source code. So the designer uses toStringCache to ensure that the String object obtained every time the toString method is called is unchanged. Imagine if you did not use toStringCache, but directly shared the value, then after calling toString method, and then operate on StringBuffer, the String object returned before changed, which violated the unchanged design concept of String object.
For the other methods are implemented by calling the method of the parent class, but all have added synchronized to ensure the effect of thread safety. Here is a function example. For other methods, see the implementation of its parent class AbstractStringBuilder. (Extract: 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);
}
Save the state of the StringBuilder object to a stream during serialization ( putting the memory object into a file ). See java.io.ObjectOutputStream for details. The difference and the scene are not clear .
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),
};