抽象类 AbstractStringBuilder 实现了接口 AppendableCharSequence ,接口 Appendable 中有三个重载的 append 方法,专门来处理字符串的添加操作。

Appendable append(CharSequence csq) throws IOException;
Appendable append(CharSequence csq, int start, int end) throws IOException;
Appendable append(char c) throws IOException;

AbstractStringBuilder 中有两个重要的字段, value[]count 。value 是用来字符存储的,count 记录 value 实际使用的字符数。比如 value = new char[100] ,将 'a'、'b'、'c' 放入 value 中,此时 count=3。

char[] value;
int count;

对应的, AbstractStringBuilder 中有两个方法分别来获取 value 的长度和实际使用的长度 count,value 的长度其实就是容量。getValue 方法可以获取 value [],此方法被 final 修饰,不可被子类重写。

@Override
public int length() {
    return count;
}
public int capacity() {
    return value.length;
}
final char[] getValue() {
    return value;
}

AbstractStringBuilder 有两个构造方法,其中无参构造方法是为了子类的序列化,有参构造传入了一个整数来构造一个指定容量的字符数组,并赋值给 value。

AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}

接下来就是对容量的操作。

ensureCapacity 方法确保 value 的容量至少是指定容量,如果指定容量大小比 value 原来的容量大小大就重新创建一个数组赋值给 value。此方法在 append 方法的操作中很重要。

新数组的容量由 newCapacity 方法确定,首先扩容至原容量的 2 倍加 2,这样扩容可能是因为如果通过有参构造方法构造一个容量为 0 的字符串,那么仅仅乘以 2 容量永远都为 0。如果扩容 2 倍加 2 还是达不到指定的容量,那么就直接扩容至指定的容量,否则的话就是继续用该容量。

但此时就需要考虑该容量是否超出了 int 值的范围,是否超出了数组的最大容量。int 数值溢出会变为负数,数组的最大容量是 Integer 的最大值减 8,减 8 是因为数组需要存储一些额外的头信息,并且这些信息需要的容量不会超过 8。

如果新容量超出 int 值范围或者超出数组最大容量,就在指定容量和数组最大容量中选择最大的作为新数组的容量。

public void ensureCapacity(int minimumCapacity) {
    if (minimumCapacity > 0)
        ensureCapacityInternal(minimumCapacity);
}
private void ensureCapacityInternal(int minimumCapacity) {
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                              newCapacity(minimumCapacity));
    }
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private int newCapacity(int minCapacity) {
    int newCapacity = (value.length << 1) + 2;
    if (newCapacity - minCapacity < 0) {
        newCapacity = minCapacity;
    }
    return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
        ? hugeCapacity(minCapacity)
        : newCapacity;
}
private int hugeCapacity(int minCapacity) {
    if (Integer.MAX_VALUE - minCapacity < 0) { 
        throw new OutOfMemoryError();
    }
    return (minCapacity > MAX_ARRAY_SIZE)
        ? minCapacity : MAX_ARRAY_SIZE;
}

trimToSize() 方法是将字符串的容量降为已被使用的容量大小。

public void trimToSize() {
    if (count < value.length) {
        value = Arrays.copyOf(value, count);
    }
}

容量可以被改变,字符串的长度也可以被改变,调用 Array 的 fill 方法填充数组并将 count 值设为新的长度。但要保证新的长度合法。

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;
}

然后就是对字符进行操作的方法,charAt 方法是重写 CharSequence 的方法。

public char charAt(int index)
public int codePointAt(int index)
public int codePointBefore(int index)
public int codePointCount(int beginIndex, int endIndex)
public int offsetByCodePoints(int index, int codePointOffset)
public void setCharAt(int index, char ch)

getChars 方法可以将调用该方法的字符串复制到指定的字符数组中,将 value 的 [srcBegin, srcEnd) 复制到 ts 数组的 [dstBegin, dstBegin+value.length) 中。

public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
{
    if (srcBegin < 0)
        throw new StringIndexOutOfBoundsException(srcBegin);
    if ((srcEnd < 0) || (srcEnd > count))
        throw new StringIndexOutOfBoundsException(srcEnd);
    if (srcBegin > srcEnd)
        throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
    System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

接下来是一系列的 append 方法,在字符串后面添加字符串。其中 appendNull 就是在字符串后面添加 "null",append (boolean b) 就是在字符串后面添加 "true" 或 "false",append (int i) 就是在字符串后面添加 i 的字符串。

public AbstractStringBuilder append(Object obj);
public AbstractStringBuilder append(String str);
public AbstractStringBuilder append(StringBuffer sb);
AbstractStringBuilder append(AbstractStringBuilder asb);
public AbstractStringBuilder append(CharSequence s);
private AbstractStringBuilder appendNull();
public AbstractStringBuilder append(CharSequence s, int start, int end);
public AbstractStringBuilder append(char[] str);
public AbstractStringBuilder append(char str[], int offset, int len);
public AbstractStringBuilder append(boolean b);
public AbstractStringBuilder append(char c);
public AbstractStringBuilder append(int i);
public AbstractStringBuilder append(long l);
public AbstractStringBuilder append(float f);
public AbstractStringBuilder append(double d);
public AbstractStringBuilder appendCodePoint(int codePoint);

还有在字符串中间插入字符串的 insert 方法。核心就是首先进行扩容,然后将 value 指定位置之后的字符向后移动给被插入的字符串空出位置,最后插入字符串。

public AbstractStringBuilder insert(int index, char[] str, int offset, int len);
public AbstractStringBuilder insert(int offset, Object obj);
public AbstractStringBuilder insert(int offset, String str);
public AbstractStringBuilder insert(int offset, char[] str);
public AbstractStringBuilder insert(int dstOffset, CharSequence s);
public AbstractStringBuilder insert(int dstOffset, CharSequence s, int start, int end);
public AbstractStringBuilder insert(int offset, boolean b);
public AbstractStringBuilder insert(int offset, char c);
public AbstractStringBuilder insert(int offset, int i);
public AbstractStringBuilder insert(int offset, long l);
public AbstractStringBuilder insert(int offset, float f);
public AbstractStringBuilder insert(int offset, double d);

delete 方法可以删除字符串的子串。

public AbstractStringBuilder delete(int start, int end);
public AbstractStringBuilder deleteCharAt(int index);

replace 方法替换字符串的子串。

public AbstractStringBuilder replace(int start, int end, String str);

substring 方法返回字符串的子串。

public String substring(int start);
public CharSequence subSequence(int start, int end);
public String substring(int start, int end);

indexOf 方法返回子串在字符串中的位置。

public int indexOf(String str);
public int indexOf(String str, int fromIndex);
public int lastIndexOf(String str);
public int lastIndexOf(String str, int fromIndex);

resverse 方法将字符串反转,以后可以借鉴该方法的实现,从中间开始

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;
}
private void reverseAllValidSurrogatePairs() {
    for (int i = 0; i < count - 1; i++) {
        char c2 = value[i];
        if (Character.isLowSurrogate(c2)) {
            char c1 = value[i + 1];
            if (Character.isHighSurrogate(c1)) {
                value[i++] = c1;
                value[i] = c2;
            }
        }
    }
}

最后,该类提供了一个抽象的 toString 方法,该方法继承自 CharSequence 接口。

@Override
public abstract String toString();