StringBuilder源码解析
StringBuilder
StringBuilder是一个继承AbstractStringBuilder,实现Serializable和CharSequence接口的类
public final class StringBuilder extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
// 此处不粘贴源码
}
初始化
1.StringBuilder
public StringBuilder(String str) {
//调用父类构造方法创建一个定长的空数组,参数传入:字符串长度+16,看1.1
super(str.length() + 16);
// 向空数组中填数据,看1.2
append(str);
}
1.1 父类AbstractStringBuilder构造方法
char[] value;// 存储字符串内容
AbstractStringBuilder(int capacity) {
value = new char[capacity];// new一个定长的数组
}
1.2 StringBuilder.append方法
public StringBuilder append(String str) {
super.append(str);//调用父类append方法实现,看1.2.1
return this;
}
1.2.1 父类AbstractStringBuilder.append方法
int count;//长度计算值:记录value的长度,默认初始值:0
public AbstractStringBuilder append(String str) {
// 判断传入的字符串是否为null
if (str == null)
return appendNull();
int len = str.length();//再次获取字符串长度
ensureCapacityInternal(count + len);//创建时,count=0,看1.2.1.1
//调用String类的getChars方法,生成一个定长的新数组,将str的数据拷贝进value中,这一步结束后value完成赋值
str.getChars(0, len, value, count);
count += len;// 长度计算值+=当前数组长度
return this;
}
1.2.1.1 父类AbstractStringBuilder.ensureCapacityInternal方法
/**
* @param minimumCapacity append方法中传入的count+len
*
*/
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
// 判断传入的参数(长度)是否大于刚生成的数组长度
if (minimumCapacity - value.length > 0) {
/**
* 若大于,证明刚生成的数组容量不满足要求
* 1.调用newCapacity计算扩容后总量(看1.2.1.1.1)
* 2.调用Arrays.copyOf方法,重新生成一个数组,并将原数组数据拷贝进去
* */
value = Arrays.copyOf(value,newCapacity(minimumCapacity));
}
}
1.2.1.1.1 newCapacity 获取“待扩容的数组长度”
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;// 2^31-1 -8
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;// 计算扩容后的数组长度,将原来的数组扩容1倍多2
if (newCapacity - minCapacity < 0) {
// 若“待扩容后的数组长度”还是小于“要求最小扩容量”,则直接使用“要求最小扩容量”作为“待扩容后的数组长度”
newCapacity = minCapacity;
}
/**
* 再一次验证,这次时为了防止容量越界,若MAX_ARRAY_SIZE都小于“待扩容后的数组长度”,看1.2.1.1.1.1
* */
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
Arrays.copyOf方法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; }
1.2.1.1.1.1 AbstractStringBuilder.hugeCapacity方法
/**
* 取“待扩容后的数组长度”,在“待扩容后的数组长度”大于MAX_ARRAY_SIZE成立时被调用
* 1.验证“待扩容后的数组长度”是否大于Integer.MAX_VALUE(2^31-1),若大于证明“待扩容后的数组长度”超界了,直接抛异常
* 2.上一步验证通过,接着判断“待扩容后的数组长度”和MAX_ARRAY_SIZE(2^31-1 -8)谁大,取最大者
*/
private int hugeCapacity(int minCapacity) {
if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE)
? minCapacity : MAX_ARRAY_SIZE;
}
由源码可知
StringBuilder的大量操作都是由其父类AbstractStringBuilder实现的StringBuilder是线程不安全类StringBuilder有容量限制,且当前容量不满足要求时会重新创建char[],都由父类AbstractStringBuilder实现;网上都在说StringBuilder动态扩容,这种说法也对也不对,对是因为它在不满足要求时的确扩容了,而且扩容量给到了原容量的1倍+2,一定程度上这会减少new char[]造成的消耗,不对是因为它不在原数组上扩容,是直接创建新char[newLenth],然后拷贝旧数组数据实现扩容StringBuilder初始化数组长度:字符串长度+16
Tips
其实在操作StringBuilder的变量时跟一跟源码,就会发现,
AbstractStringBuilder实现了StringBuilder的绝大部分方法,就连存储字符串的char[] value也是由AbstractStringBuilder提供的
本文来自博客园,作者:勤匠,转载请注明原文链接:https://www.cnblogs.com/JarryShu/articles/18179193

浙公网安备 33010602011771号