java.lang.StringBuffer源码分析

本文深入剖析了StringBuffer类的内部实现,包括其线程安全特性的实现方式,以及如何通过缓存来提高toString方法的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

StringBuffer是一个线程安全的可变序列的字符数组对象,它与StringBuilder一样,继承父类AbstractStringBuilder。在多线程环境中,当方法操作是必须被同步,StringBuffer内的方法被同步化时,以实现跟在单线程中操作一样的一致性。

 

public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
    //一个缓存用来存储最后一次调用toString返回的值,每当StringBuffer被修改就把该缓存清空
    private transient char[] toStringCache;

    public StringBuffer() {
        super(16);
    }

    public StringBuffer(int capacity) {
        super(capacity);
    }

    //...more constructs,提供与父类一致的构造器,StringBuffer的构造器总是调用父类的构造器

    
    @Override
    public synchronized int length() {//返回容器中字符的数量
        return count;
    }

    @Override
    public synchronized int capacity() {//返回容器的大小
        return value.length;
    }


    @Override
    public synchronized void ensureCapacity(int minimumCapacity) {//保证容器足够大
        if (minimumCapacity > value.length) {
            expandCapacity(minimumCapacity);
        }
    }

    @Override
    public synchronized void trimToSize() {//将容器的大小与容器的字符数量变成一致的
        super.trimToSize();
    }

    //setLength是修改了StringBuffer,所以要把toStringCache设置为null
    public synchronized void setLength(int newLength) {
        toStringCache = null;
        super.setLength(newLength);
    }

    //...append,insert方法还有其他需要同步化的方法都是覆盖父类,用synchronized使方法同步化,同时那些修改了StringBuffer的方法,需要先把toStringCache设置为null

    //下面几个insert方法没有用synchronized来实现同步化,上面的解释说这些方法的同步化是通过调用其他StringBuffer方法来实现的
    public StringBuffer insert(int dstOffset, CharSequence s) {
        // Note, synchronization achieved via invocations of other StringBuffer methods
        // after narrowing of s to specific type
        // Ditto for toStringCache clearing
        super.insert(dstOffset, s);
        return this;
    }


       public  StringBuffer insert(int offset, boolean b) {
        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
        // after conversion of b to String by super class method
        // Ditto for toStringCache clearing
        super.insert(offset, b);
        return this;
    }

    public StringBuffer insert(int offset, int i) {
        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
        // after conversion of i to String by super class method
        // Ditto for toStringCache clearing
        super.insert(offset, i);
        return this;
    }

    public StringBuffer insert(int offset, long l) {
        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
        // after conversion of l to String by super class method
        // Ditto for toStringCache clearing
        super.insert(offset, l);
        return this;
    }

    public StringBuffer insert(int offset, float f) {
        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
        // after conversion of f to String by super class method
        // Ditto for toStringCache clearing
        super.insert(offset, f);
        return this;
    }

    public StringBuffer insert(int offset, double d) {
        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
        // after conversion of d to String by super class method
        // Ditto for toStringCache clearing
        super.insert(offset, d);
        return this;
    }

    public int indexOf(String str) {
        // Note, synchronization achieved via invocations of other StringBuffer methods
        return super.indexOf(str);
    }

    public int lastIndexOf(String str) {
        // Note, synchronization achieved via invocations of other StringBuffer methods
        return lastIndexOf(str, count);
    }

    //这个toString方法很重要,如果toStringCache为null时,会把当前的value复制一份新的给它,否则返回String(toStringCache)
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

    //下面的三个方法是为了实现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),
    };

    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();
    }

    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);
    }

从上面源码可知,StringBuffer将父类非线程安全的方法都覆盖实现同步化,它自己拥有一个toStringCache的缓存,当这个缓存为空的时候,就知道StringBuffer被修改过了,这时候调用toString方法,就能得到被修改后最新的值。

转载于:https://www.cnblogs.com/13jhzeng/p/5624424.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值