Java源代码分析之StringBuffer

StringBuffer源码分析

每个Java程序员基本都了解的

  • 长度可变字符操作工具类
  • 在多线程环境下线程安全
  • 额,好像想不到其他的呢?

所以需要去阅读并分析源码

  • StringBuffer类图,如下

StringBuffer类图

可以看到 StringBuffer继承自AbstractStringBuilder(实现了Appendable接口),实现了SerializableCharSequence接口。

  • 源码分析(加入自己所理解的注释)
package java.lang;   // jdk此包实现类基本都需要了解

import java.util.Arrays;

// 线程安全、字符串可变的字符操作类
public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{

    /**
     * 最后一次修改后的缓存值(字符数组保存),只要修改了value,那么就会重置
     */
    private transient char[] toStringCache;

    /** 序列号, 对象序列化和反序列化需要的唯一标识版本号 */
    static final long serialVersionUID = 3388685877147921107L;

    /**
     * 默认构造方法
     */
    public StringBuffer() {
        /**
        *  AbstractStringBuilder(int capacity) {
        *    value = new char[capacity];
        *  }
        *  调用父类的构造方法,默认初始化容量为capacity = 16 
        *  貌似看到的所有jdk中实现类涉及初始化容量的大小都为16,加上一点扩容机制(后面详细分析)
        */
        super(16);
    }

    /**
     * 带一个参数的构造方法,可以指定初始化容量
     */
    public StringBuffer(int capacity) {
        super(capacity);
    }

    /**
     * 带一个参数构造方法,与前一个不同,这是指定一个String来初始化
     */
    public StringBuffer(String str) {
        // 这里可以注意下,指定String初始化StringBuffer的时候指定容量大小为String的长度加上16
        super(str.length() + 16);
        //然后追加到value中
        append(str);
    }

    /**
     * 与前一个类似
     */
    public StringBuffer(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }
     //获取字符数量,效率低。。。对象锁
    @Override
    public synchronized int length() {
        return count;
    }
     // 获取容量,效率低。。。对象锁
    @Override
    public synchronized int capacity() {
        return value.length;
    }

    // 确保容量不小于minimumCapacity
    @Override
    public synchronized void ensureCapacity(int minimumCapacity) {
        if (minimumCapacity > value.length) {
            // 当最小容量值(传进来的参数值)大于value.length(这个其实就是容量),那么扩容
            expandCapacity(minimumCapacity);
        }
    }

    /**
     * 将value数组中没有存入元素的部分去掉(类似去空格)
     * 此时容量大小和size大小相等
     */
    @Override
    public synchronized void trimToSize() {
        super.trimToSize();
        //直接调用AbstractStringBuilder已经实现的方法
        /*
        public void trimToSize() {
          if (count < value.length) {
             value = Arrays.copyOf(value, count);
          }
        }
        */
    }

    /**
     * 扩充字符串容量到newLength,并且用空格填充
     */
    @Override
    public synchronized void setLength(int newLength) {
        toStringCache = null;
        //调用父类函数
        super.setLength(newLength);
        /*
          public void setLength(int newLength) {
          if (newLength < 0)
              throw new StringIndexOutOfBoundsException(newLength);
          // 首先扩充容量(函数说明在下面)
          ensureCapacityInternal(newLength);

          if (count < newLength) {
              Arrays.fill(value, count, newLength, '\0');// 然后扩充部分用空格填充
          }

           count = newLength;
        }*/
        // 首先扩充容量(判断是否符合扩充条件)
        /*
        private void ensureCapacityInternal(int minimumCapacity) {
           if (minimumCapacity - value.length > 0)
               expandCapacity(minimumCapacity);
           }
         */
         //扩充容量  value.length * 2 + 2;
        /*
        void expandCapacity(int minimumCapacity) {
           int newCapacity = value.length * 2 + 2;
           if (newCapacity - minimumCapacity < 0)
               newCapacity = minimumCapacity;
           if (newCapacity < 0) {
              //溢出,这一步基本不会发生吧,Error那就是致命错误了
              if (minimumCapacity < 0) // overflow
                  throw new OutOfMemoryError();
              //设置容量最大值
              newCapacity = Integer.MAX_VALUE;
           }
           // 扩充容量,分配内存存储空间
           value = Arrays.copyOf(value, newCapacity);
         }
        */
        /*
        public static char[] copyOf(char[] original, int newLength) {
           char[] copy = new char[newLength];
           //分配内存
           System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
           return copy;
        }
        */
    }

    /**
     * 根据指定索引获取字符,效率慢啊。。。对象锁
     */
    @Override
    public synchronized char charAt(int index) {
        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        return value[index];
    }

    /**
     * 开始看到这个确实是一脸懵逼啊,还是一步一步看吧,返回代码点(Unicode代码点)
     */
    @Override
    public synchronized int codePointAt(int index) {
        return super.codePointAt(index);
        //父类AbstractStringBuilder方法
        /*
           public int codePointAt(int index) {
             if ((index < 0) || (index >= count)) {
                throw new StringIndexOutOfBoundsException(index);
             }
             return Character.codePointAtImpl(value, index, count);
           }
        */
    /*char:java中,char类型为16位,原本用于表示一个字符。但是后来发现,16位已经不够表示所有的字符,所以后来发展出了用代码点表示字符的方法。

代码点:是指编码字符集中,字符所对应的数字。有效范围从U+0000到U+10FFFF。其中U+0000到U+FFFF为基本字符,U+10000到U+10FFFF为增补字符。

代码单元:对代码点进行编码得到的1或2个16位序列(UTF-16)。其中基本字符的代码点直接用一个相同值的代码单元表示,增补字符的代码点用两个代码单元进行编码,编码值来自U+D800到U+DFFF,这个范围内没有数字用于表示字符,因此程序可以识别出当前字符是单单元的基本字符,还是双单元的增补字符。*/
        //Character静态方法
        /*
        static int codePointAtImpl(char[] a, int index, int limit) {
        char c1 = a[index];
        if (isHighSurrogate(c1) && ++index < limit) {
            char c2 = a[index];
            if (isLowSurrogate(c2)) {
                return toCodePoint(c1, c2);
            }
        }
        return c1;
    }
    */
    }

    /**
     * 返回前一个代码点(一个代码点可能是一个代码单元也有可能是两个代码单元)
     */
    @Override
    public synchronized int codePointBefore(int index) {
         //Character静态方法最终提供实现
        return super.codePointBefore(index);
    }

    /**
     * 返回代码点个数
     */
    @Override
    public synchronized int codePointCount(int beginIndex, int endIndex) {
        return super.codePointCount(beginIndex, endIndex);
        //Character静态方法最终提供实现
        /*
        static int codePointCountImpl(char[] a, int offset, int count) {
        int endIndex = offset + count;
        int n = count;
        for (int i = offset; i < endIndex; ) {
            if (isHighSurrogate(a[i++]) && i < endIndex &&
                isLowSurrogate(a[i])) {
                n--;
                i++;
            }
        }
           return n;
        }*/
    }

    /**
     * 给定初始偏移索引和代码点偏移量,返回对应索引
     * 需要注意的是增补字符会用两个代码单元表示一个代码点(基本字符一个代码点对应一个代码单元),
     *  一个代码单元用一个char表示,然后index索引是指char数组(value存放数据的数组)的索引
     */
    @Override
    public synchronized int offsetByCodePoints(int index, int codePointOffset) {
        return super.offsetByCodePoints(index, codePointOffset);
        // offsetByCodePoints 用法
        /*
           char[] ch = Character.toChars(0x10400);
           String str = new String(ch);
           int retval = str.offsetByCodePoints(0, 1);
           System.out.println("reval = " + retval);//2
        */
    }

    /**
     * 根据指定索引以及偏移量将字符串拷贝到dst
     */
    @Override
    public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
                                      int dstBegin)
    {
        super.getChars(srcBegin, srcEnd, dst, dstBegin);
        //System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }

    /**
     * 根据索引修改字符串中某个字符值
     */
    @Override
    public synchronized void setCharAt(int index, char ch) {
        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        toStringCache = null;//清除,只要修改了value,此值就会clear
        value[index] = ch;
    }
    //追加
    @Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
        //父类实现AbstractStringBuilder
        /*
        public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        //System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
        count += len;
        return this;
        }
        */
        //追加null
        /*
        private AbstractStringBuilder appendNull() {
           int c = count;
           ensureCapacityInternal(c + 4);
           final char[] value = this.value;
           value[c++] = 'n';
           value[c++] = 'u';
           value[c++] = 'l';
           value[c++] = 'l';
           count = c;
           return this;
       }
       */
    }
// 同上
    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

    /**
     * 同上
     * @since 1.4
     */
    public synchronized StringBuffer append(StringBuffer sb) {
        toStringCache = null;
        super.append(sb);
        return this;
    }

    /**
     * @since 1.8
     */
    @Override
    synchronized StringBuffer append(AbstractStringBuilder asb) {
        toStringCache = null;
        super.append(asb);
        return this;
    }

    /**
     * 同上
     * @since 1.5
     */
    @Override
    public synchronized StringBuffer append(CharSequence s) {
        toStringCache = null;
        super.append(s);
        return this;
        /*
        public AbstractStringBuilder append(CharSequence s) {
        if (s == null)
            return appendNull();
        if (s instanceof String)
            return this.append((String)s);
        if (s instanceof AbstractStringBuilder)
            return this.append((AbstractStringBuilder)s);

        return this.append(s, 0, s.length());
    }*/
    }
    //同上
    @Override
    public synchronized StringBuffer append(CharSequence s, int start, int end)
    {
        toStringCache = null;
        super.append(s, start, end);
        return this;
    }
   //同上
    @Override
    public synchronized StringBuffer append(char[] str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

     //同上
    @Override
    public synchronized StringBuffer append(char[] str, int offset, int len) {
        toStringCache = null;
        super.append(str, offset, len);
        return this;
    }
 //同上
    @Override
    public synchronized StringBuffer append(boolean b) {
        toStringCache = null;
        super.append(b);
        return this;
        /*
        public AbstractStringBuilder append(boolean b) {
        if (b) {
            ensureCapacityInternal(count + 4);
            value[count++] = 't';
            value[count++] = 'r';
            value[count++] = 'u';
            value[count++] = 'e';
        } else {
            ensureCapacityInternal(count + 5);
            value[count++] = 'f';
            value[count++] = 'a';
            value[count++] = 'l';
            value[count++] = 's';
            value[count++] = 'e';
        }
        return this;
        }*/
    }

//同上
    @Override
    public synchronized StringBuffer append(char c) {
        toStringCache = null;
        super.append(c);
        return this;
    }
//同上
    @Override
    public synchronized StringBuffer append(int i) {
        toStringCache = null;
        super.append(i);
        return this;
    }

    /**
     * 明白了之前分析的代码点以及代码单元,这个就没啥分析的,很容易理解
     */
    @Override
    public synchronized StringBuffer appendCodePoint(int codePoint) {
        toStringCache = null;
        super.appendCodePoint(codePoint);
        return this;
        /*
         public AbstractStringBuilder appendCodePoint(int codePoint) {
        final int count = this.count;

        if (Character.isBmpCodePoint(codePoint)) {
            ensureCapacityInternal(count + 1);
            value[count] = (char) codePoint;
            this.count = count + 1;
        } else if (Character.isValidCodePoint(codePoint)) {
            ensureCapacityInternal(count + 2);
            Character.toSurrogates(codePoint, value, count);
            this.count = count + 2;
        } else {
            throw new IllegalArgumentException();
        }
        return this;
    }*/
    }

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

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

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

    /**
     *  删除字符
     */
    @Override
    public synchronized StringBuffer delete(int start, int end) {
        toStringCache = null;
        super.delete(start, end);
        // 实现:左移
        //System.arraycopy(value, start+len, value, start, count-end);
        return this;
    }

    /**
     * 同上
     */
    @Override
    public synchronized StringBuffer deleteCharAt(int index) {
        toStringCache = null;
        super.deleteCharAt(index);
        return this;
    }

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

    /**
     * 不存在内存泄漏
     */
    @Override
    public synchronized String substring(int start) {
        return substring(start, count);
        //new String(value, start, end - start);
        // 没有复用char[]
    }

    /**
     * 同上
     */
    @Override
    public synchronized CharSequence subSequence(int start, int end) {
        return super.substring(start, end);
    }

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

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     * @since      1.2
     */
    @Override
    public synchronized StringBuffer insert(int index, char[] str, int offset,
                                            int len)
    {
        toStringCache = null;
        super.insert(index, str, offset, len);
        // System.arraycopy(value, index, value, index + len, count - index);
        // System.arraycopy(str, offset, value, index, len);
        return this;
    }

    /**
     * 同上
     */
    @Override
    public synchronized StringBuffer insert(int offset, Object obj) {
        toStringCache = null;
        super.insert(offset, String.valueOf(obj));
        return this;
    }

    /**
     * 同上
     */
    @Override
    public synchronized StringBuffer insert(int offset, String str) {
        toStringCache = null;
        super.insert(offset, str);
        return this;
    }

    /**
     * 同上
     */
    @Override
    public synchronized StringBuffer insert(int offset, char[] str) {
        toStringCache = null;
        super.insert(offset, str);
        return this;
    }

    /**
     * 同上
     * 此方法不同步, 而且也没有 toStringCache = null;
     * 如果需要同步,那么需要将CharSequence s转化为specific type特定类型
     * @since      1.5
     */
    @Override
    public StringBuffer insert(int dstOffset, CharSequence s) {
        super.insert(dstOffset, s);
        return this;
    }

    /**
     * 同上
     */
    @Override
    public synchronized StringBuffer insert(int dstOffset, CharSequence s,
            int start, int end)
    {
        toStringCache = null;
        super.insert(dstOffset, s, start, end);
        return this;
    }

     /**
     * 同上
     * 此方法不同步, 而且也没有 toStringCache = null;
     * 如果需要同步,那么需要将boolean b转化为specific type特定类型(String)
     * @since      1.5
     */
    @Override
    public  StringBuffer insert(int offset, boolean b) {
        super.insert(offset, b);
        return this;
    }

    /**
     * 同上
     */
    @Override
    public synchronized StringBuffer insert(int offset, char c) {
        toStringCache = null;
        super.insert(offset, c);
        return this;
    }

    /**
     * 同上
     * 此方法不同步, 而且也没有 toStringCache = null;
     * 如果需要同步,那么需要将int i转化为specific type特定类型(String)
     * @since      1.5
     */
    @Override
    public StringBuffer insert(int offset, int i) {
        super.insert(offset, i);
        return this;
    }

    /**
     * 同上
     * 此方法不同步, 而且也没有 toStringCache = null;
     * 如果需要同步,那么需要将long l转化为specific type特定类型(String)
     * @since      1.5
     */
    @Override
    public StringBuffer insert(int offset, long l) {
        super.insert(offset, l);
        return this;
    }

   /**
     * 同上
     * 此方法不同步, 而且也没有 toStringCache = null;
     * 如果需要同步,那么需要将float f转化为specific type特定类型(String)
     * @since      1.5
     */
    @Override
    public StringBuffer insert(int offset, float f) {
        super.insert(offset, f);
        return this;
    }

    /**
     * 同上
     */
    @Override
    public StringBuffer insert(int offset, double d) {
        super.insert(offset, d);
        return this;
    }

    /**
     * 非线程安全
     */
    @Override
    public int indexOf(String str) {
        return super.indexOf(str);
    }

    /**
     * 同上,但是线程安全
     */
    @Override
    public synchronized int indexOf(String str, int fromIndex) {
        return super.indexOf(str, fromIndex);
    }

    /**
     * 调用下面一个方法,从而保证了线程安全了
     */
    @Override
    public int lastIndexOf(String str) {
        return lastIndexOf(str, count);
    }

    /**
     * @since      1.4
     */
    @Override
    public synchronized int lastIndexOf(String str, int fromIndex) {
        return super.lastIndexOf(str, fromIndex);
    }

    /**
     * 反转
     */
    @Override
    public synchronized StringBuffer reverse() {
        toStringCache = null;
        super.reverse();
        return this;
        /*
        public AbstractStringBuilder reverse() {
        boolean hasSurrogates = false;
        int n = count - 1;
        //首先 收尾对调,达到反转的效果
        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;
            if (Character.isSurrogate(cj) ||
                Character.isSurrogate(ck)) {
                hasSurrogates = true;
            }
        }
        // 考虑到存在增补字符,需要成对校验
        if (hasSurrogates) {
            reverseAllValidSurrogatePairs();
        }
        return this;
    }*/
    }
//toStringCache之前都不知道这个字段的含义,看到这里似乎看懂了,。是提高toString函数的效率,不用每次都是 调用
//  Arrays.copyOfRange。。。但是字符串修改后这个值得clear
//线程安全
    @Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

    // 自定义序列化字段
    //**transient 用于指定哪个字段不被默认序列化,如public transient int a; 
     //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),
    };

    /**
     *  序列化大到ObjectOutputStream
     */
    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);
    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值