为什么ArrayList#rangeCheck不检查索引是否为负数?

6
ArrayList的get、set和remove方法在调用rangeCheck方法时,首先会执行该方法。这个方法不会检查索引是否为负数,它只会检查索引是否大于或等于数组的长度。Java文档解释了这个原因:如果索引为负数,则会抛出ArrayIndexOutOfBoundsException异常。
private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}

根据Java语言规范,如果索引不仅是负数,而且大于或等于数组长度,则数组访问会抛出ArrayIndexOutOfBoundsException。
所有的数组访问都在运行时进行检查;尝试使用小于零或大于等于数组长度的索引会导致抛出ArrayIndexOutOfBoundsException异常。
我认为rangeCheck应该同时检查负数和大于或等于情况,或者为了提高性能,两种都不检查。为什么rangeCheck不检查索引是否为负数?

4
因为它不需要这样做,接下来的数组访问已经完成了这个操作,就像你引用的那句话所说的一样。 - user207421
1个回答

12
非常简单,因为在 ArrayList 中,后备数组的大小可能大于当前大小。
在当前实现中,每当超过当前最大容量时,ArrayList 的后备数组容量会增加1.5倍。默认的初始容量为10,当您尝试将第11个元素添加到列表时,该数组将重新分配,并具有15的容量。当您超过15时,它将变为22等等。
在任何给定时间,容量很可能大于 ArrayList 中当前元素的数量。
检查负索引由 JVM(在后备数组上)处理,而 ArrayList 本身只需要在当前列表的上限处进行检查。

增长策略的细节没有具体说明,除了添加元素具有恒定的摊销时间成本。 - user207421
不,你描述的是“向量”。目前的ArrayList实现增长因子为1.5。 - user207421
你说得对,我已经有一段时间没有查看grepcode了。或者我可能将其与HashMap中桶数组的增量混淆了。再次编辑。 - Jim Garrison
谢谢!我不知道“支持数组可能比当前大小更大”的事实。 - kshi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接