类定义
abstract class AbstractStringBuilder implements Appendable, CharSequence {}
抽象类,是StringBuffer和StringBuilder的父类,实现了两个接口:
-
CharSequence
a. 该接口规定了需要实现该字符序列的长度:length();
b. 可以取得下标为index的的字符:charAt(int index);
c. 可以得到该字符序列的一个子字符序列: subSequence(int start, int end); -
Appendable
这个接口有3个方法,都是append添加字符或字符序列的
a. append(CharSequence csq) :如何添加一个字符序列
b. append(CharSequence csq, int start, int end) :如何添加一个字符序列的一部分
c. append(char c) :如何添加一个字符
成员变量
-
char[] value;
该字符序列的具体存储 -
int count;
实际存储的数量,注意和capacity的区别,count是value中实际存了数据的长度,capacity是value的总长度,也就是value.length
还需要注意的是,value和count都不是final修饰的,是可变的,也就是修改和扩容,修改就是修改这个char数组的某个值,而扩容并非真的扩容,扩容是通过调用Arrays.copyOf
来实现的,而Arrays.copyOf
其实是new了一个新的数组来实现的
public static char[] copyOf(char[] original, int newLength) {
char[] copy = new char[newLength]; //新建了一个数组
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
构造方法
AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
重要知识点
length和capacity两个char数组指针
length方法返回的是value当前实际使用的数量,capacity返回的是value的总长度
@Override
public int length() {
return count;
}
public int capacity() {
return value.length;
}
扩容
ensureCapacity提供了判断char数组容量加上需要增加的容量是否大雨数组最大边界,expandCapacity是AbstractStringBuilder实现扩容的方法。扩容的大小是 (capacity+1)乘以2,如果(capacity+1)*2 小于传入的参数(所需的容量大小),直接用所需的容量大小作为capacity。扩容的方式是通过用Arrays.copyOf来进行数组拷贝。
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2; //先计算原来(value.length(也就是capacity)+1)*2
if (newCapacity - minimumCapacity < 0)
//如果计算后的newCapacity还是比传入的值小,直接用传入的值作为新的capacity
newCapacity = minimumCapacity;
if (newCapacity < 0) {
//进行了溢出判断,防止出现原来数组的(capacity+1)*2>65535的情况,如果出现了直接将65535作为新的capacity
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
//用Arrays.copyOf来进行数组拷贝,看Arrays源码可知,其实是new了一个新的数组
value = Arrays.copyOf(value, newCapacity);
}
getValue
不同与String无法获取value,AbstractStringBuilder提供了直接获取value进行操作的方法。
append
append是最重要的方式。细看源码,主要可以分为两种append方式
-
System.arraycopy的方式
例如String、Stringbuffer、int、float、long等都是通过XX.getChars的方法来追加,但getChars方法底层源码都还是采用System.arraycopy实现的。
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; }
str.getChars(0, len, value, count);
,这句代码是append追加的关键,是通过String的getChars方法将,str字符串的char字符数组,从0到len复制(源码中使用了System.arraycopy)给AbstractStringBuilder的value,并从value的count位置起追加复制char数组是直接调用System.arraycopy实现追加的
Object会先调用String.valueOf方法,然后再调用上面的传入参数为String的append重载方法。也因此,当Object为null时,String.valueOf返回的字符串为“null”
public AbstractStringBuilder append(Object obj) { return append(String.valueOf(obj)); }
-
在原来的value后面赋值的方式
例如appendNull、appendBoolean、appendChar,都是直接给value后面还没有使用的索引赋值的
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; }
hashcode和equals
看了AbstractStringBuilder的源码,没有找到hashcode和equals这两个方法,所以这两个方法还是用的Object方法(与String不同)