提问人:Poison 提问时间:2/28/2022 最后编辑:Poison 更新时间:2/28/2022 访问量:556
为什么 java.util.ArrayList 类中的 rangeCheck 方法不检查负索引?[关闭]
Why doesn't the rangeCheck method in the java.util.ArrayList class check for negative index? [closed]
问:
/**
* Checks if the given index is in range. If not, throws an appropriate
* runtime exception. This method does *not* check if the index is
* negative: It is always used immediately prior to an array access,
* which throws an ArrayIndexOutOfBoundsException if index is negative.
*/
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
来自: jdk/ArrayList.java at jdk8-b120 · openjdk/jdk ·GitHub的
如果我们编写以下代码,则两个索引都越界,但异常类型不同。
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("");
try {
list.get(-1);
} catch (Exception e) {
e.printStackTrace();
}
try {
list.get(1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出如下:
java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(ArrayList.java:424)
at java.util.ArrayList.get(ArrayList.java:437)
at Test.main(Test.java:11)
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:659)
at java.util.ArrayList.get(ArrayList.java:435)
at Test.main(Test.java:17)
相关问题:
- 为什么方法在检查负指数?
rangeCheckForAdd
java.util.ArrayList
- 为什么不进行索引越界检查?
java.util.Arrays.ArrayList
让我感到困惑的是为什么它们的实现不一致?这些方法是由不同的人编写的,有自己的编程风格吗?换句话说,如果最终会触发越界异常,则无需检查。
答:
这是一个微优化。为了代码清晰起见,您可能希望两者使用相同的例外,但是当您处于热循环中时,您需要避免不必要的操作。 作为一个旧类,其效果可能因时代和 JDK 版本而异。如果有人有足够的兴趣,他们可以用 1.8 和更新的 JDK 对其进行基准测试,看看它对优化有多大。ArrayList
get()
由于访问负数组索引无论如何都会失败,因此无需检查它。但是,的大小并不总是与其内部数组的大小相同,因此需要显式检查。ArrayList
至于为什么要检查负指数,好问题。无论如何,添加速度很慢,因此微优化不会有太大区别。也许他们希望在这里保持一致的错误消息。rangeCheckForAdd
评论
对数组访问的范围检查检查数组索引是否在范围 中。0 <= index < elementData.length
对于 a,索引的有效范围仅为 ,其中 。由于数组访问不能正确检查上限(可能小于 ),因此类必须确保不违反上限。java.util.ArrayList
0 <= index < size
size <= elementData.length
size
elementData.length
ArrayList
不需要检查下限,因为下限始终在访问数组时进行验证。0
elementData
为什么 rangeCheckForAdd
检查负索引?
添加元素时,可能需要在添加新元素之前增加数组的大小。但是,如果索引无效(负数或大于大小),则不希望增加数组。因此,在这种情况下,有必要在执行其他任何操作之前进行完整的边界检查()。elementData
elementData
0 <= index <= size
为什么 java.util.Arrays.ArrayList
不进行越界检查?
a 的大小正好是后备数组的大小。因此,不需要单独的边界检查(如 ,其中大小可以小于后备数组的大小)。java.util.Arrays.ArrayList
java.util.ArrayList
评论
raneCheckForAdd