JDK1.8 源码分析(三)--StringBuffer

220 阅读6分钟

1. 类的定义

public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence

从StringBuffer定义中可以看出

  • StringBuffer是final修饰的类,不可继承

  • 继承了AbstractStringBuilder类

  • 实现了java.io.Serializable接口,可以序列化

  • 实现了CharSequence接口,表示StringBuffer一个可读的char序列

2. 字段属性

//从父类AbstractStringBuilder继承
 char[] value;
 //从父类继承
 int count;
 //缓存,toString的时候才缓存,修改就置为null
 private transient char[] toStringCache;
 //序列化版本号
 static final long serialVersionUID = 4383685877147921099L;

从上面可以看出

  • StringBuffer 本质是一个char数组
  • 保存了char数组中可以用字符的长度,注意:count不是char数组的长度
  • toStringCache缓存了char数组可用字符的值,transient表示不可序列化

3. 构造方法

//空构造函数,默认指定char的长度为16
 public StringBuffer() {
 super(16);
 }
 //传入char数组的初始化长度
 public StringBuffer(int capacity) {
 super(capacity);
 }
 //传入一个字符串,默认char数组长度为字符串长度加16
 //将str保存到char数组中去
 public StringBuffer(String str) {
 super(str.length() + 16);
 append(str);
 }
 //传入一个CharSequence对象,默认char数组长度为CharSequence对象长度加16
 //将CharSequence对象保存到char数组中去
 public StringBuffer(CharSequence seq) {
 this(seq.length() + 16);
 append(seq);
 }

从构造方法中可以看出

  • StringBuffer中的char数组默认长度是16

  • 可以自己指定默认长度

  • 构造方法可以传入String对象和CharSequence对象,预留16个char的长度

4. 方法

  • StringBuffer中所有的方法不都是使用synchronized修饰的,因此StringBuffer是线程安全的

length 方法

@Override
    public synchronized int length() {
        //返回count表示可用字符的数量,跟char数组长度不一定相等

        return count;
    }

capacity 方法

@Override
    public synchronized int capacity() {
        //value的长度表示容量

        return value.length;
    }

ensureCapacity 方法

@Override
    public synchronized void ensureCapacity(int minimumCapacity) {
        //调用父类方法

        super.ensureCapacity(minimumCapacity);
    }
 public void ensureCapacity(int minimumCapacity) {
         //参数验证

        if (minimumCapacity > 0)
            ensureCapacityInternal(minimumCapacity);
    }
 private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        //确保容量,容量不足则扩容到minimumCapacity

        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

charAt 方法

@Override
    public synchronized char charAt(int index) {
        //参数检查

        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        //直接返回

        return value[index];
    }

append 方法

@Override
    public synchronized StringBuffer append(String str) {
        //将缓存置为null

        toStringCache = null;
        //调用父类的方法

        super.append(str);
        return this;
    }

    public AbstractStringBuilder append(String str) {
        //参数检查
        if (str == null)
            return appendNull();
        //获取参数的长度
        int len = str.length();
        //char数组长度检查,如果长度不够会进行扩容,扩容的大小为count+len
        ensureCapacityInternal(count + len);
        //将传入的str添加到char数组后面
        str.getChars(0, len, value, count);
        //重新设置当前可用字符的数量
        count += len;
        return this;
    }

delete 方法

 @Override
    public synchronized StringBuffer delete(int start, int end) {
        //将缓存置为null

        toStringCache = null;
        //调用父类方法

        super.delete(start, end);
        return this;
    }

public AbstractStringBuilder delete(int start, int end) {
        //参数检查
        if (start < 0)
            throw new StringIndexOutOfBoundsException(start);
        //如果结尾大于可用字符的数量把end的值设置为count
        if (end > count)
            end = count;
        //参数检查
        if (start > end)
            throw new StringIndexOutOfBoundsException();
        //计算需要删除的数量
        int len = end - start;
        if (len > 0) {
            //把start+len作为起始位置,count作为结束位置去覆盖start作为起始位置,覆盖数量为count-end
            //类似于后面的前移,覆盖中间删除部分
            System.arraycopy(value, start + len, value, start, count - end);
            //重新计算可用字符长度,这里删除的话应该减小
            count -= len;
        }
        return this;
    }

replace 方法

 @Override
    public synchronized StringBuffer replace(int start, int end, String str) {
        //将缓存置为null
        toStringCache = null;
        //调用父类方法
        super.replace(start, end, str);
        return this;
    }

public AbstractStringBuilder delete(int start, int end) {
        //参数检查
        if (start < 0)
            throw new StringIndexOutOfBoundsException(start);
        //如果结尾大于可用字符的数量把end的值设置为count
        if (end > count)
            end = count;
        //参数检查
        if (start > end)
            throw new StringIndexOutOfBoundsException();
        //计算需要删除的数量
        int len = end - start;
        if (len > 0) {
            //把start+len作为起始位置,count作为结束位置去覆盖start作为起始位置,覆盖数量为count-end
            //类似于后面的前移,覆盖中间删除部分
            System.arraycopy(value, start + len, value, start, count - end);
            //重新计算可用字符长度,这里删除的话应该减小
            count -= len;
        }
        return this;
    }

substring 方法

@Override
    public synchronized String substring(int start, int end) {
        //调用父类方法
        return super.substring(start, end);
    }

public String substring(int start, int end) {
        //参数验证

        if (start < 0)
            throw new StringIndexOutOfBoundsException(start);
        if (end > count)
            throw new StringIndexOutOfBoundsException(end);
        if (start > end)
            throw new StringIndexOutOfBoundsException(end - start);
        //从valule中返回start到end的字符串
        return new String(value, start, end - start);
    }
  • substring(int start)的实质是sbustring(start, count)

insert 方法

@Override
    public synchronized StringBuffer insert(int offset, String str) {
        //缓存设置为null
        toStringCache = null;
        //调用父类方法
        super.insert(offset, str);
        return this;
    }

public AbstractStringBuilder insert(int offset, String str) {
        //验证参数合法性
        if ((offset < 0) || (offset > length()))
            throw new StringIndexOutOfBoundsException(offset);
        //如果传入的String为空,替换为”null“字符串
        if (str == null)
            str = "null";
        //获取插入字符串的长度
        int len = str.length();
        //检查char数组容量,容量不够则扩容
        ensureCapacityInternal(count + len);
        //把offset作为起始位置,count作为结束位置去覆盖offset + len作为起始位置,覆盖数量为count - offset
        //类似于offset后面的后移,空出插入部分
        System.arraycopy(value, offset, value, offset + len, count - offset);
        //把str的内容填充进去
        str.getChars(value, offset);
        //重新计算count的值
        count += len;
        return this;
    }

indexOf 方法

@Override
    public int indexOf(String str) {
        //注意,这个方法没有用synchronized修饰
        //调用父类方法
        return super.indexOf(str);
    }

@Override
    public synchronized int indexOf(String str, int fromIndex) {
        //调用父类方法
        return super.indexOf(str, fromIndex);
    }

public int indexOf(String str, int fromIndex) {
        //最后调用String的indexOf
        return String.indexOf(value, 0, count, str, fromIndex);
    }

lastIndexOf 方法

@Override
    public int lastIndexOf(String str) {
        //注意,这个方法没有用synchronized修饰
        //调用父类方法

        return lastIndexOf(str, count);
    }

 @Override
    public synchronized int lastIndexOf(String str, int fromIndex) {
        //调用父类方法
        return super.lastIndexOf(str, fromIndex);
    }

public int lastIndexOf(String str, int fromIndex) {
        //最后调用的是String的lastIndexOf方法

        return String.lastIndexOf(value, 0, count, str, fromIndex);
    }

reverse 方法

 @Override
    public synchronized StringBuffer reverse() {
        //将缓存置为null

        toStringCache = null;
        //调用父类方法

        super.reverse();
        return this;
    }

public AbstractStringBuilder reverse() {
        //是否含有unicode编码,包含Unicode编码的话,替换后高低位会改变位置
        boolean hasSurrogates = false;
        int n = count - 1;
        //采取二分法 n-1>>1 等同于 (n-1)/2
        for (int j = (n - 1) >> 1; j >= 0; j--) {
            //根据对称性左右替换
            int k = n - j;
            char cj = value[j];
            char ck = value[k];
            value[j] = ck;
            value[k] = cj;
            //判断是否含有unicode编码
            if (Character.isSurrogate(cj) ||
                    Character.isSurrogate(ck)) {
                hasSurrogates = true;
            }
        }
        //包含unicode编码
        if (hasSurrogates) {
            reverseAllValidSurrogatePairs();
        }
        return this;
    }

/**
     * Outlined helper method for reverse()
     */
    private void reverseAllValidSurrogatePairs() {
        for (int i = 0; i < count - 1; i++) {
            char c2 = value[i];
            //如果包含Unicode编码,将高低位位置改变回来
            if (Character.isLowSurrogate(c2)) {
                char c1 = value[i + 1];
                if (Character.isHighSurrogate(c1)) {
                    value[i++] = c1;
                    value[i] = c2;
                }
            }
        }
    }

toString 方法

@Override
    public synchronized String toString() {
        //如果缓存为空,重新设置缓存

        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        //直接使用缓存的数组

        return new String(toStringCache, true);
    }