StringBuilder被final关键字修饰,表明是不可变类,继承自抽象类AbstractStringBuilder。
AbstractStringBuilder的底层结构
AbstractStringBuilder底层封装了一个字符串数组:
char[] value;
与String
不同,它不是使用final修饰
的,可以修改。另外,与String
不同,字符数组中不一定所有位置都已经被使用,它有一个实例变量,表示数组中已经使用的字符个数,定义如下:
int count;
StringBuilder
继承自AbstractStringBuilder
,它的默认构造方法是:
public StringBuilder() {
super(16);
}
调用父类的构造方法,父类对应的构造方法是:
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
也就是说, super(16) 这句代码,内部会创建一个长度为16的字符数组,count的默认值为0。
AbstractStringBuilder append的实现
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
append
会直接拷贝字符到内部的字符数组中,如果字符数组长度不够,会进行扩展,实际使用的长度用count
体现。具体来说,ensureCapacityInternal(count+len)
会确保数组的长度足以容纳新添加的字符,str.getChars
会拷贝新添加的字符到字符数组中,count+=len
会增加实际使用的长度。
ensureCapacityInternal
的代码如下:
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
如果字符数组的长度小于需要的长度,则调用newCapacity进行扩展,newCapacity的代码是:
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
扩展的逻辑是,分配一个足够长度的新数组,然后将原内容拷贝到这个新数组中,最后让内部的字符数组指向这个新数组,这个逻辑主要靠下面这句代码实现:
value = Arrays.copyOf(value, newCapacity(minimumCapacity));
StringBuilder toString实现
字符串构建完后,我们来看toString代码:
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}