zoukankan      html  css  js  c++  java
  • JDK源码之AbstractStringBuilder类分析

    一 概述

    二 实现接口

    AbstractStringBuilder实现了两个接口:

    1. Appendable
      • 概述:
        Appendable的实现类的对象可以附加字符序列和值.
        要追加的字符应该是Unicode字符表示中描述的有效Unicode字符。注意,补充字符可能由多个16位字符值组成。
        对于多线程访问不一定是安全的。线程安全是扩展和实现这个接口的类的职责。
        IO流操作的写类基本都实现了这个接口,比如BufferedWriter, CharArrayWriter, CharBuffer, FileWriter等,还有StringBuffer和StringBuild也实现了这个接口
      • 接口定义的方法:
        /**
         * 添加CharSequence序列到当前对象,并返回当前对象
         */
        Appendable append(CharSequence csq) throws IOException;
    
        /**
         * 添加CharSequence序列参数的子序列,按照参数进行分割,到当前对象
         */
        Appendable append(CharSequence csq, int start, int end) throws IOException;
    
        /**
         * 添加char值到当前对象
         */
        Appendable append(char c) throws IOException;
    
    1. CharSequence

      这个接口就不多说了,表示char 值的一个可读序列(有序集合),

    三 源码解析

    1 属性

        // 表示AbstractStringBuilder的值,可变的byte数组,jdk9之前是char数组
        byte[] value;
    
        // coder编码值,jdk9之后添加的编码标识,和String的编码coder是一样的
        byte coder;
    
        // 当前字符串已经使用的byte数组中的长度,增删改查的同时需要维护这个属性值
        int count;
    
        //空byte数组,用于无参构造器初始化,jdk9之后新增的
        private static final byte[] EMPTYVALUE = new byte[0];
    
        // 能创建数组长度的最大值
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    

    2 构造器

        /**
         * 无参构造器,vlaue默认赋值为一个长度为0的byte数组
         */
        AbstractStringBuilder() {
            value = EMPTYVALUE;
        }
    
        /**
         * 根据参数创建指定长度的byte数组
         */
        AbstractStringBuilder(int capacity) {
            // 根据是否压缩标识创建单字节或者双字节存储
            if (COMPACT_STRINGS) {
                value = new byte[capacity];
                coder = LATIN1;
            } else {
                value = StringUTF16.newBytesFor(capacity);//将capacity << 1 ,即创建capacity乘以2的大小byte数组
                coder = UTF16;
            }
        }
    

    3 基本api

        //jdk11新增方法,比较大小
        int compareTo(AbstractStringBuilder another) {
            if (this == another) {
                return 0;
            }
    
            byte val1[] = value;
            byte val2[] = another.value;
            int count1 = this.count;
            int count2 = another.count;
    
            if (coder == another.coder) {
                return isLatin1() ? StringLatin1.compareTo(val1, val2, count1, count2)
                        : StringUTF16.compareTo(val1, val2, count1, count2);
            }
            return isLatin1() ? StringLatin1.compareToUTF16(val1, val2, count1, count2)
                    : StringUTF16.compareToLatin1(val1, val2, count1, count2);
        }
    
        //返回当前字符串实际的长度
        @Override
        public int length() {
            return count;
        }
    
        //返回当前字符所占用byte数组的长度, >= length()
        public int capacity() {
            return value.length >> coder;
        }
    
        //确保当前value的数组长度至少等于指定的参数
        public void ensureCapacity(int minimumCapacity) {
            if (minimumCapacity > 0) {
                ensureCapacityInternal(minimumCapacity);
            }
        }
    
        private void ensureCapacityInternal(int minimumCapacity) {
            // 防止append的时候数组越界
            int oldCapacity = value.length >> coder;
            if (minimumCapacity - oldCapacity > 0) { //参数 > 当前byte数组长度
                // 创建新长度大小的byte数组,并将value值进行copy,重新赋值给当前value
                value = Arrays.copyOf(value,
                        newCapacity(minimumCapacity) << coder);
            }
        }
    
        /**
         * 判断给定参数是否溢出或者小于0,并返回合理的数组长度
         */
        private int newCapacity(int minCapacity) {
            // overflow-conscious code
            int oldCapacity = value.length >> coder;
            int newCapacity = (oldCapacity << 1) + 2;
            //每次扩容,最少扩大原来的2倍+2
            if (newCapacity - minCapacity < 0) {
                newCapacity = minCapacity;
            }
            int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
            // 验证扩容值是否溢出
            return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
                    ? hugeCapacity(minCapacity)
                    : newCapacity;
        }
    
        //越界检查.是否超过最大值
        private int hugeCapacity(int minCapacity) {
            int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
            int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
            if (UNSAFE_BOUND - minCapacity < 0) { // overflow
                throw new OutOfMemoryError();
            }
            return (minCapacity > SAFE_BOUND)
                    ? minCapacity : SAFE_BOUND;
        }
    
        //如果编码是Latin,则byte数组扩容为原来两倍,并将原有的值按双字节存储,编码改为UTF16
        private void inflate() {
            if (!isLatin1()) {
                return;
            }
            byte[] buf = StringUTF16.newBytesFor(value.length);
            StringLatin1.inflate(value, 0, buf, 0, count);
            this.value = buf;
            this.coder = UTF16;
        }
    
        //如果value数组的容量有多余的,那么就把多余的全部都释放掉
        public void trimToSize() {
            int length = count << coder; //实际使用了的长度
            if (length < value.length) { // byte数组长度
                value = Arrays.copyOf(value, length);
            }
        }
    
        /**
         * 强制增大实际长度count的大小,容量如果不够就用 expandCapacity()扩大;
         * 将扩大的部分全部用’’(ASCII码中的null)来初始化
         */
        public void setLength(int newLength) {
            if (newLength < 0) {
                throw new StringIndexOutOfBoundsException(newLength);
            }
            ensureCapacityInternal(newLength);
            if (count < newLength) {
                if (isLatin1()) {
                    //使用null填充
                    StringLatin1.fillNull(value, count, newLength);
                } else {
                    StringUTF16.fillNull(value, count, newLength);
                }
            }
            count = newLength;
        }
    
        // 抽象方法,需要子类自己实现
        @Override
        public abstract String toString();
    

    4 增(append)

        /**
         * 添加Object,实际是把对象转为String,调用添加String方法
         */
        public AbstractStringBuilder append(Object obj) {
            return append(String.valueOf(obj));
        }
    
        /**
         * 添加String
         */
        public AbstractStringBuilder append(String str) {
            if (str == null) {
                return appendNull();
            }
            int len = str.length();
            //对 byte数组扩容,确保长度大于 count+len
            ensureCapacityInternal(count + len);
            //讲str追加到byte数组中
            putStringAt(count, str);
            count += len; //修改实际占用长度
            return this;
        }
    
        //添加 StringBuffer
        public AbstractStringBuilder append(StringBuffer sb) {
            return this.append((AbstractStringBuilder)sb);
        }
    
        /**
         * jdk1.8新加的方法,逻辑跟添加String是一样的
         */
        AbstractStringBuilder append(AbstractStringBuilder asb) {
            if (asb == null) {
                return appendNull();
            }
            int len = asb.length();
            ensureCapacityInternal(count + len);
            if (getCoder() != asb.getCoder()) {
                inflate();
            }
            asb.getBytes(value, count, coder);
            count += len;
            return this;
        }
    
        // 添加 CharSequence,实现Appendable接口的方法
        @Override
        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());
        }
    
        // 添加字符串 "null"
        private AbstractStringBuilder appendNull() {
            ensureCapacityInternal(count + 4);
            int count = this.count;
            byte[] val = this.value;
            if (isLatin1()) {
                val[count++] = 'n';
                val[count++] = 'u';
                val[count++] = 'l';
                val[count++] = 'l';
            } else {
                count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
            }
            this.count = count;
            return this;
        }
    
    
        //指定位置添加 s
        @Override
        public AbstractStringBuilder append(CharSequence s, int start, int end) {
            if (s == null) {
                s = "null";
            }
            checkRange(start, end, s.length());
            int len = end - start;
            ensureCapacityInternal(count + len);
            appendChars(s, start, end);
            return this;
        }
    
        // 添加插入数组
        public AbstractStringBuilder append(char[] str) {
            int len = str.length;
            ensureCapacityInternal(count + len);
            appendChars(str, 0, len);
            return this;
        }
    
        /**
         * 添加插入数组, 指定开始位置和添加的长度
         */
        public AbstractStringBuilder append(char str[], int offset, int len) {
            int end = offset + len;
            checkRange(offset, end, str.length);
            ensureCapacityInternal(count + len);
            appendChars(str, offset, end);
            return this;
        }
    
        // 添加 'true' 或者 'false'
        public AbstractStringBuilder append(boolean b) {
            ensureCapacityInternal(count + (b ? 4 : 5));
            int count = this.count;
            byte[] val = this.value;
            if (isLatin1()) {
                if (b) {
                    val[count++] = 't';
                    val[count++] = 'r';
                    val[count++] = 'u';
                    val[count++] = 'e';
                } else {
                    val[count++] = 'f';
                    val[count++] = 'a';
                    val[count++] = 'l';
                    val[count++] = 's';
                    val[count++] = 'e';
                }
            } else {
                if (b) {
                    count = StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');
                } else {
                    count = StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
                }
            }
            this.count = count;
            return this;
        }
    
        //添加unicode代码点
        public AbstractStringBuilder appendCodePoint(int codePoint) {
            if (Character.isBmpCodePoint(codePoint)) {
                return append((char)codePoint);
            }
            return append(Character.toChars(codePoint));
        }
        // 添加 char
        @Override
        public AbstractStringBuilder append(char c) {
            ensureCapacityInternal(count + 1);
            if (isLatin1() && StringLatin1.canEncode(c)) {
                value[count++] = (byte)c;
            } else {
                if (isLatin1()) {
                    inflate();
                }
                StringUTF16.putCharSB(value, count++, c);
            }
            return this;
        }
    
        // 添加 int,以下都是添加number
        public AbstractStringBuilder append(int i) {
            int count = this.count;
            int spaceNeeded = count + Integer.stringSize(i);
            ensureCapacityInternal(spaceNeeded);
            if (isLatin1()) {
                Integer.getChars(i, spaceNeeded, value);
            } else {
                StringUTF16.getChars(i, count, spaceNeeded, value);
            }
            this.count = spaceNeeded;
            return this;
        }
    
        public AbstractStringBuilder append(long l) {
            int count = this.count;
            int spaceNeeded = count + Long.stringSize(l);
            ensureCapacityInternal(spaceNeeded);
            if (isLatin1()) {
                Long.getChars(l, spaceNeeded, value);
            } else {
                StringUTF16.getChars(l, count, spaceNeeded, value);
            }
            this.count = spaceNeeded;
            return this;
        }
    
        public AbstractStringBuilder append(float f) {
            FloatingDecimal.appendTo(f,this);
            return this;
        }
    
        public AbstractStringBuilder append(double d) {
            FloatingDecimal.appendTo(d,this);
            return this;
        }
    
        /**
         * 在 index位置插入 char数组的一部分,这部分从是[ offset,offset + len )
         */
        public AbstractStringBuilder insert(int index, char[] str, int offset,
                                            int len)
        {
            checkOffset(index, count);
            checkRangeSIOOBE(offset, offset + len, str.length);
            ensureCapacityInternal(count + len);
            shift(index, len);
            count += len;
            putCharsAt(index, str, offset, offset + len);
            return this;
        }
    
        /**
         * 在 offset位置,插入 obj,其他像int,boolean 都是类似的用String.valueOf转然后调用插入String方法
         */
        public AbstractStringBuilder insert(int offset, Object obj) {
            return insert(offset, String.valueOf(obj));
        }
    
        public AbstractStringBuilder insert(int offset, String str) {
            checkOffset(offset, count);
            if (str == null) {
                str = "null";
            }
            int len = str.length();
            ensureCapacityInternal(count + len);
            shift(offset, len);
            count += len;
            putStringAt(offset, str);
            return this;
        }
    

    5 删

        /**
         * 删除指定位置的字符
         */
        public AbstractStringBuilder delete(int start, int end) {
            int count = this.count;
            if (end > count) {
                end = count;
            }
            checkRangeSIOOBE(start, end, count);
            int len = end - start;
            if (len > 0) {
                shift(end, -len); //调用System.arraycopy 方法
                this.count = count - len;
            }
            return this;
        }
    
        /**
         * 删除指定位置的字符
         */
        public AbstractStringBuilder deleteCharAt(int index) {
            checkIndex(index, count);
            shift(index + 1, -1); //删除 index index+1 位置的字符
            count--;
            return this;
        }
        // 将value从offset开始复制 count-offset个值,从 offset+n 开始重新赋值给value, 即删减 n 个字符
        private void shift(int offset, int n) {
            System.arraycopy(value, offset << coder,
                    value, (offset + n) << coder, (count - offset) << coder);
        }
    

    6 改

        /**
         * 用字符串str替换掉value[]数组的[start,end)部分
         */
        public AbstractStringBuilder replace(int start, int end, String str) {
            int count = this.count;
            if (end > count) {
                end = count;
            }
            checkRangeSIOOBE(start, end, count);
            int len = str.length();
            int newCount = count + len - (end - start);
            ensureCapacityInternal(newCount);//扩容
            shift(end, newCount - count);// 从指定end处开始,删除或者增加 newCount - count个值
            this.count = newCount;
            putStringAt(start, str); //从start开始添加字符
            return this;
        }
    
        //截取子字符串
        public String substring(int start) {
            return substring(start, count);
        }
    
        public String substring(int start, int end) {
            checkRangeSIOOBE(start, end, count);
            if (isLatin1()) {
                return StringLatin1.newString(value, start, end - start);
            }
            return StringUTF16.newString(value, start, end - start);
        }
    
        /**
         * 在指定index位置设置 char值
         */
        public void setCharAt(int index, char ch) {
            checkIndex(index, count);
            if (isLatin1() && StringLatin1.canEncode(ch)) {
                value[index] = (byte)ch;
            } else {
                if (isLatin1()) {
                    inflate();
                }
                StringUTF16.putCharSB(value, index, ch);
            }
        }
    
        /**
         * 将value给倒序存放(注意改变的就是本value,而不是创建了一个新的AbstractStringBuilder然后value为倒序)
         */
        public AbstractStringBuilder reverse() {
            byte[] val = this.value;
            int count = this.count;
            int coder = this.coder;
            int n = count - 1;
            if (COMPACT_STRINGS && coder == LATIN1) {
                for (int j = (n-1) >> 1; j >= 0; j--) {
                    int k = n - j;
                    byte cj = val[j];
                    val[j] = val[k];
                    val[k] = cj;
                }
            } else {
                StringUTF16.reverse(val, count);
            }
            return this;
        }
    

    7 查

        /**
         * 获取下标为index的char字符
         */
        @Override
        public char charAt(int index) {
            checkIndex(index, count);
            if (isLatin1()) {
                return (char)(value[index] & 0xff);
            }
            return StringUTF16.charAt(value, index);
        }
    
        /**
         * 获取index位置的unicode代码单位
         */
        public int codePointAt(int index) {
            int count = this.count;
            byte[] value = this.value;
            checkIndex(index, count);
            if (isLatin1()) {
                return value[index] & 0xff;
            }
            return StringUTF16.codePointAtSB(value, index, count);
        }
    
        /**
         * 将value[]的 [srcBegin, srcEnd) 拷贝到 dst[]数组的desBegin开始处
         */
        public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
        {
            checkRangeSIOOBE(srcBegin, srcEnd, count);  // compatible to old version
            int n = srcEnd - srcBegin;
            checkRange(dstBegin, dstBegin + n, dst.length);
            if (isLatin1()) {
                StringLatin1.getChars(value, srcBegin, srcEnd, dst, dstBegin);
            } else {
                StringUTF16.getChars(value, srcBegin, srcEnd, dst, dstBegin);
            }
        }
    
        //在value[]中找字符串str,若能找到,返回第一个字符串的第一个字符的下标
        public int indexOf(String str) {
            return indexOf(str, 0);
        }
    
        //从fromIndex开始,在value[]中找字符串str,若能找到,返回第一个字符串的第一个字符的下标
        public int indexOf(String str, int fromIndex) {
            return String.indexOf(value, coder, count, str, fromIndex);
        }
    
        // 从后面往前找
        public int lastIndexOf(String str) {
            return lastIndexOf(str, count);
        }
    
        // 从后面往前找
        public int lastIndexOf(String str, int fromIndex) {
            return String.lastIndexOf(value, coder, count, str, fromIndex);
        }
    
        /**
         * jdk9 新增方法,获取int流
         */
        @Override
        public IntStream chars() {
            return StreamSupport.intStream(
                    () -> {
                        byte[] val = this.value;
                        int count = this.count;
                        byte coder = this.coder;
                        return coder == LATIN1
                                ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
                                : new StringUTF16.CharsSpliterator(val, 0, count, 0);
                    },
                    Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
                    false);
        }
    
        /**
         * jdk9 新增方法,获取unicode代码点int 流
         */
        @Override
        public IntStream codePoints() {
            return StreamSupport.intStream(
                    () -> {
                        byte[] val = this.value;
                        int count = this.count;
                        byte coder = this.coder;
                        return coder == LATIN1
                                ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
                                : new StringUTF16.CodePointsSpliterator(val, 0, count, 0);
                    },
                    Spliterator.ORDERED,
                    false);
        }
    

    四 总结

    AbstractStringBuilder就是 可变 字符序列的一个纲领
    它规定了可变字符序列应该有的行为
    比如 添加字符/删除字符/更新字符/获取字符
    因为可变,所以对于可变的支持,自然是必不可少的
    另外,他作为String在很多方面的一个替代,必然也是提供了String的一些功能方法
    否则与String API 变化巨大 也是毫无意义
    因为毕竟本身就是为了描述字符序列
    所以对于AbstractStringBuilder 只需要彻底理解了他作为 可变字符序列的标准接口即可
    接口的两个实现StringBuffer和StringBuild大部分的功能也都是调用的父类方法!

  • 相关阅读:
    x32dbg之AttachHelper插件
    x32dbg插件之APIInfo
    x32dbg之Scylla脱壳插件
    x32dbg插件之strongOD(又名SharpOD)
    x32dbg新型插件之loli(萝莉)
    7 个超棒的监控工具
    成为程序员前需要做的10件事
    改良程序的11个技巧
    旧衣物捐献地址和注意事项
    一件衣服好不好,看看标签就知道
  • 原文地址:https://www.cnblogs.com/houzheng/p/12153734.html
Copyright © 2011-2022 走看看