创建时的容量
- StringBuffer buffer=new StringBuffer();//默认创建一个容量为16的对象
- StringBuffer buffer=new StringBuffer(int);//创建一个指定容量的对象
- StringBuffer buffer=new StringBuffer(String);//常见一个指定内容的对象,容量是16+字符串的长
增加新内容时,容量的变化
- append(Object obj); 在原字符序列末尾追加内容
我们追踪append()方法,最后进入newCapacity(int minCapacity)方法 - minCapacity 所需最小容量
- newCapacity 自动扩容后的容量
- 一般情况下
- 如果没有超出当前容量,那么容量不变
- 如果超出当前容量,那么将容量改为(当前容量*2+1)
- 特殊情况:
- (1) newCapacity > MAX_ARRAY_SIZE
- 但minCapacity < Integer.MAX_VALUE
- 此时返回minCapacity 和MAX_ARRAY_SIZE中的最大值
- (2)扩容后的newCapacity > 0(即没有超出int范围),并且小于MAX_ARRAY_SIZE ,直接返回扩容后的newCapacity
- (3)扩容后的newCapacity 如果大于MAX_ARRAY_SIZE ,并且所需要的minCapacity 小于Integer.MAX_VALUE的范围,那么将长度改为minCapacity
- (1) newCapacity > MAX_ARRAY_SIZE
但是我们会发现return语句有一个判断newCapacity <= 0的情况,为什么要判断这种情况? 我们下面来仔细探讨一下
- (4)newCapacity 和minCapacity都超出了Integer.MAX_VALUE 并且newCapacity - minCapacity < 0(当int类型的变量值大于Integer.MAX_VALUE 时,该变量所储存的值可能会变为负数)
- 例如
- ① int a = Integer.MAX_VALUE + 1; 此时a所储存的值为-2147483648
- ②int a = Integer.MAX_VALUE + Integer.MAX_VALUE + 3;此时a所储存的值为1
- 简单来说是int的长度是32位,首位为符号为,0代表正数1代表负数,但如果超出32位的数值又会被舍弃,所以对一个int类型的值不停的累加,符号位会从0和1之间切换,也就是说给int类型的数据a赋一个大于Integer.MAX_VALUE的值,那么最终a中存放的数据可能是正数也可能是负数
- 但是数组和String的最大长度length属性是32位的有符号整数,它的最大值是2的31次幂-1
- 所以说如果newCapacity 和minCapacity实际想表达的数值超出了Integer.MAX_VALUE ,那么他们两个的值一定是负数
- 如果newCapacity 和minCapacity都是负数
- 那么newCapacity-minCapacity也可能是负数,此时让newCapacity =minCapacity,所以会产生newCapacity <= 0,然后判断Integer.MAX_VALUE - minCapacity < 0也成立( Integer.MAX_VALUE-(-1)结果为-2147483648 ),说明此时超出了int的范围,于是抛异常
- newCapacity-minCapacity是正数,此时newCapacity不变,newCapacity <= 0,然后判断Integer.MAX_VALUE - minCapacity < 0也成立,最后依然会判断出抛异常
- 关于newCapacity == 0是一个特殊情况,当value.length已经等于Integer.MAX_VALUE时,(value.length << 1) + 2;的值恰好为0,因为此时进行的是扩容操作所以minCapacity必然大于value.length,即minCapacity是一个负数,因为newCapacity == 0所以会判断 Integer.MAX_VALUE- minCapacity < 0,此时必然成立,抛异常
- 例如
(如果理解有误还请大佬及时告知)
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private int newCapacity(int minCapacity) {
//minCapacity是当前所需要的最小容量
//value.length是当前的容量
// 先将当前容量扩大二倍并+2
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) { // overflow
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE)
? minCapacity : MAX_ARRAY_SIZE;
}