1.实现接口
/**
* Whenever an operation occurs involving a source sequence (such as
* appending or inserting from a source sequence), this class synchronizes
* only on the string buffer performing the operation, not on the source.
* Note that while {@code StringBuffer} is designed to be safe to use
* concurrently from multiple threads, if the constructor or the
* {@code append} or {@code insert} operation is passed a source sequence
* that is shared across threads, the calling code must ensure
* that the operation has a consistent and unchanging view of the source
* sequence for the duration of the operation.
* //只对append或insert的字符缓冲区线程安全,对源字符不保证
*/
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
...
static final long serialVersionUID = 3388685877147921107L;
// Serializable fields for StringBuffer. Stringbuffer特有序列化
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),
};
/**
* readObject is called to restore the state of the StringBuffer from
* a stream.
*/
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();
}
/**
* readObject is called to restore the state of the StringBuffer from
* a stream.
*/
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);
}
}
2.toStringCache
/**
* A cache of the last value returned by toString. Cleared
* whenever the StringBuffer is modified.
*/
private transient char[] toStringCache;
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
- 缓存数组,每次对Stringbuffer修改都会将该数组清空,而toString方法会将当前数组value中值赋给该数组toStringCache,返回一个新String对象
- transient 关键字修饰的变量在序列化的时候不会被保存到文件中,也就是通过序列化后再被反序列化后读取这个变量不会有值。被static修饰的变量应该也是不会被序列化的,因为只有堆内存会被序列化.所以静态变量会天生不会被序列化。那这里被static修饰的变量反序列化后有值又是什么鬼 ,这是因为静态变量在方法区,本来流里面就没有写入静态变量,我们打印静态变量当然会去方法区查找,我们当前 jvm 中有所以静态变量在序列化后任然有值。
3.构造方法
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);
}
把16这个数字记住就完事了
3.其他方法(都用synchronized修饰)
@Override
public synchronized int length() {
return count;
}
@Override
public synchronized void setLength(int newLength) {
toStringCache = null;
super.setLength(newLength);
}
....
先toStringCache清空,在调用父类AbstractStringBuilder中的方法
参考资料:
https://blog.csdn.net/weixin_30484247/article/details/95115707?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2
https://www.cnblogs.com/xiaoxiaole/p/7457788.html
https://www.jianshu.com/p/4ef12eb46cbf