• StringBuilder
    • append的实现
    • toString实现

    StringBuilder

    StringBuilder类也封装了一个字符数组,定义如下:

    1. char[] value;

    String不同,它不是final的,可以修改。另外,与String不同,字符数组中不一定所有位置都已经被使用,它有一个实例变量,表示数组中已经使用的字符个数,定义如下:

    1. int count;

    StringBuilder继承自AbstractStringBuilder,它的默认构造方法是:

    1. public StringBuilder() {
    2. super(16);
    3. }

    调用父类的构造方法,父类对应的构造方法是:

    1. AbstractStringBuilder(int capacity) {
    2. value = new char[capacity];
    3. }

    也就是说,new StringBuilder()这句代码,内部会创建一个长度为16的字符数组,count的默认值为0。

    append的实现

    1. public AbstractStringBuilder append(String str) {
    2. if (str == null) str = "null";
    3. int len = str.length();
    4. ensureCapacityInternal(count + len);
    5. str.getChars(0, len, value, count);
    6. count += len;
    7. return this;
    8. }

    append会直接拷贝字符到内部的字符数组中,如果字符数组长度不够,会进行扩展,实际使用的长度用count体现。具体来说,ensureCapacityInternal(count+len)会确保数组的长度足以容纳新添加的字符,str.getChars会拷贝新添加的字符到字符数组中,count+=len会增加实际使用的长度。

    ensureCapacityInternal的代码如下:

    1. private void ensureCapacityInternal(int minimumCapacity) {
    2. if (minimumCapacity - value.length > 0)
    3. expandCapacity(minimumCapacity);
    4. }

    如果字符数组的长度小于需要的长度,则调用expandCapacity进行扩展,expandCapacity的代码是:

    1. void expandCapacity(int minimumCapacity) {
    2. int newCapacity = value.length * 2 + 2;
    3. if (newCapacity - minimumCapacity < 0)
    4. newCapacity = minimumCapacity;
    5. if (newCapacity < 0) {
    6. if (minimumCapacity < 0)
    7. throw new OutOfMemoryError();
    8. newCapacity = Integer.MAX_VALUE;
    9. }
    10. value = Arrays.copyOf(value, newCapacity);
    11. }

    扩展的逻辑是,分配一个足够长度的新数组,然后将原内容拷贝到这个新数组中,最后让内部的字符数组指向这个新数组,这个逻辑主要靠下面这句代码实现:

    1. value = Arrays.copyOf(value, newCapacity);

    toString实现

    字符串构建完后,我们来看toString代码:

    1. public String toString() {
    2. return new String(value, 0, count);
    3. }