StringBuffer扩容问题(源码解读)

创建时的容量

  • 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
      • 此时返回minCapacityMAX_ARRAY_SIZE中的最大值
    • (2)扩容后的newCapacity > 0(即没有超出int范围),并且小于MAX_ARRAY_SIZE ,直接返回扩容后的newCapacity
    • (3)扩容后的newCapacity 如果大于MAX_ARRAY_SIZE ,并且所需要的minCapacity 小于Integer.MAX_VALUE的范围,那么将长度改为minCapacity

但是我们会发现return语句有一个判断newCapacity <= 0的情况,为什么要判断这种情况? 我们下面来仔细探讨一下

  • (4)newCapacityminCapacity都超出了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
      • 所以说如果newCapacityminCapacity实际想表达的数值超出了Integer.MAX_VALUE ,那么他们两个的值一定是负数
    • 如果newCapacityminCapacity都是负数
      • 那么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;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值