StringBuilder和StringBuffer

2018-03-25  本文已影响0人  0x70e8

StringBuilder和StringBuffer

StringBuilder和StringBuffer都是抽象类AbstractStringBuilder的实现类,抽象类ASB实现了大部分的核心功能,最主要的append方法,是在ASB中写好的,子类中append基本都是调用此方法。
StringBuffer和StringBuilder的功能基本一致,可以说StringBuffer是StringBuilder的同步版本。

看一下ASB。

AbstractStringBuilder

定义和基本属性

实际上StringBuilder,是String类的可变版本,它低层也是char数组,像ArrayList类一样动态扩容,只是这个数组没有被限制修改,也没有final限定符,String类的“修改”是指向新的字符串,StringBuilder的修改就是直接修改低层char数组。

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     */
    char[] value;

    /**
     * The count is the number of characters used.
     */
    int count;

    /**
     * This no-arg constructor is necessary for serialization of subclasses.
     */
    AbstractStringBuilder() {
    }

    /**
     * Creates an AbstractStringBuilder of the specified capacity.
     */
    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }
    // ...
}
Append方法
  1. append怎么实现的
    看下SB的核心使用方法append,ASB一共重载了14个append方法,最核心的差不多是这个:
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        // 检查char数组是否需要扩容
        ensureCapacityInternal(count + len);
        //  使用了String类的char数组拷贝,把要追加的str copy到value的后面(以count为beginIndex)
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

所以append的实现就是把新的字符串的char数组的元素,放到原来数组里面。这个放置动作,是借助System.arraycopy方法。
看下ASB是如何动态扩容的:

    /**
     * This implements the expansion semantics of ensureCapacity with no
     * size check or synchronization.
     */
    void expandCapacity(int minimumCapacity) {
        int newCapacity = value.length * 2 + 2;
        if (newCapacity - minimumCapacity < 0)
            newCapacity = minimumCapacity;
        if (newCapacity < 0) {
            if (minimumCapacity < 0) // overflow
                throw new OutOfMemoryError();
            newCapacity = Integer.MAX_VALUE;
        }
        value = Arrays.copyOf(value, newCapacity);
    }

可以看到最后一句,把value指向新的数组,(这也是为什么value变量没有使用final的原因)。
对于String类来说,String的value是final的,String类的char数组不能动态扩容。一次初始化的字符串就是贯穿它的生命周期的长度,往后的“修改”都是创建的新的String对象返回的。String类对象不可变是因为内部char数组没有开放修改一定要牢记心中。
ArrayList(基于对象数组)的动态扩容,也是使用的数组copy(Arrays.copyOf)。

  1. append null
    ASB是支持append null的,而且它的处理方法是直接追加{'n','u','l','l'}数组:
    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;
    }
insert方法

insert方法低层实现是对数组的copy操作。

    public AbstractStringBuilder insert(int index, char[] str, int offset,
                                        int len)
    {
        if ((index < 0) || (index > length()))
            throw new StringIndexOutOfBoundsException(index);
        if ((offset < 0) || (len < 0) || (offset > str.length - len))
            throw new StringIndexOutOfBoundsException(
                "offset " + offset + ", len " + len + ", str.length "
                + str.length);
        ensureCapacityInternal(count + len);
        System.arraycopy(value, index, value, index + len, count - index);
        System.arraycopy(str, offset, value, index, len);
        count += len;
        return this;
    }

StringBuilder和StringBuffer

StringBuffer和StringBuilder,实现了ASB,前者线程安全,后者不是。
二者在实现时基本是调用super方法,核心都在ASB里面了。

上一篇下一篇

猜你喜欢

热点阅读