jdk1.0

image.png

StringBuffer类是一个具体类,继承了AbstractStringBuiler抽象类,实现了序列化接口和可读字符序列接口。
该类被final,不能被继承和重写里面的方法,可变字符序列,效率低,线程安全。
之前已经有了StringBuilder类,为什么还需要StringBuffer类,因为StringBuilder类在多线程的情况下就会出现问题,所以添加了一个新的类StringBuffer。在每个类可能出现并发问题的方法中添加synchronized同步锁,因此性能比StringBuilder类更低。

一、成员属性

  1. private transient char[] toStringCache;
  2. static final long serialVersionUID = 3388685877147921107L;

和StringBuilder类的一个区别,多了一个toStringCache字段,该字段是用于toString方法的。我们知道toString方法重新生成的String对象,会共享StringBuffer对象中的toStringCache属性,每次对StringBuffer进行修改,都会将其置为null。

二、构造方法

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

和StringBuilder类类似。默认初始化16个容量存放字符,如果是字符串或者可读字符序列,在其长度的基础上再加上16个空间。

三、主要方法

3.1 ensureCapacity(int)

    @Override
    public synchronized void ensureCapacity(int minimumCapacity) {
        super.ensureCapacity(minimumCapacity);
    }

在append、insert时需要考虑容量的问题,同时也需要考虑线程的安全问题,因此添加了同步关键字,其底层逻辑基本不变。

四、常用方法

4.1 toString()

    @Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

根据缓存toStringCache来创建字符串对象。会维护每次最新字符串,如果缓存为空,通过会拷贝,否则根据缓存进行创建一个字符串。

4.2 charAt(int)

    @Override
    public synchronized char charAt(int index) {
        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        return value[index];
    }


返回指定索引位置的字符。

4.3 getChars(int,int,char[],int)

    @Override
    public synchronized void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin){
        super.getChars(srcBegin, srcEnd, dst, dstBegin);
    }

得到字符串中的字符数组。调用的是抽象类AbstractStringBuilder中的方法,实现的原理:调用了数组的拷贝方法。

4.4 append(String)

    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

向字符串后面追加一个字符串。使用了同步锁,线程安全。具体的实现是调用父类中的逻辑,其中将缓存进行了清空操作。

4.5 replace(int,int,String)

     @Override
    public synchronized StringBuffer replace(int start, int end, String str) {
        toStringCache = null;
        super.replace(start, end, str);
        return this;
    }

在指定的一块区域替换为一个字符串,起始位置前和结束位置后的字符串保持不变,只有中间部分的字符串会被取代。线程安全,具体实现调用父类中的方法。

4.6 substring(int,int)

    @Override
    public synchronized String substring(int start, int end) {
        return super.substring(start, end);
    }

返回字符串中的子串。

4.7 indexOf(String,int)

    @Override
    public synchronized int indexOf(String str, int fromIndex) {
        return super.indexOf(str, fromIndex);
    }

返回指定字符串在原字符串中的位置,开始查找位置可以我们自己提供。

4.8 reverse()

    @Override
    public synchronized StringBuffer reverse() {
        toStringCache = null;
        super.reverse();
        return this;
    }

将字符串进行反转。

五、序列化与反序列化

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

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

遇到的问题

  1. toStringCache是什么时候被赋值的或者进行修改的。
  2. 什么是序列化与反序列化