谢谢“MartinDai”按照这个老哥的建议,调试了一波,很有效。
我陷入的问题有点钻牛角尖了,或者是理解能力不够。
总结:
数组size值发生溢出,发生在第二个判断 if (newCapacity - maxArraySize > 0) = true时,即size要足够大,我才考虑数组会溢出的问题。
正常情况下,每次size扩容1.5倍。当size扩大1.5倍发生int的溢出时,就每次进行最小扩容(+1)就可以了。第一个判断 if (newCapacity - minCapacity < 0) 这个就是为这个溢出准备的。
还有一个问题:为什么扩容的倍数为1.5 而不选择其他倍数?
//抛异常的情况:
//数组原大小oldCapacity 已经为int的最大值,此时再次调用grow()扩容minCapacity发生溢出,进入hugeCapacity() 抛出异常。 这是size会溢出的情况,只有size大于nteger.MAX_VALUE - 8 时,才开始考虑是不是抛出溢出异常
public static void main(String[] args) {
int maxArraySize = Integer.MAX_VALUE - 8;
int oldCapacity = Integer.MAX_VALUE;
int minCapacity = oldCapacity + 1;
// overflow-conscious code
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 1.5倍扩容大小 - 元素个数
// 正常情况下,1.5倍的扩容 肯定大于 元素个数,肯定不需要频繁的扩容,所以一次来大一点,至于为什么是1.5倍,这个就不知道了。
// 当 1.5倍扩容发生int的溢出时,就每次进行最小扩容(+1)就可以了。
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
//newCapacity大于maxArraySize 才考虑进入这个方法
if (newCapacity - maxArraySize > 0) {
newCapacity = hugeCapacity(minCapacity);
}
System.out.println(newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
{
throw new OutOfMemoryError();
}
return (minCapacity > Integer.MAX_VALUE - 8) ?
Integer.MAX_VALUE :
Integer.MAX_VALUE - 8;
}
}