为什么 java.util.ArrayList class 中的 rangeCheck 方法不检查负索引?
Why doesn't the rangeCheck method in the java.util.ArrayList class check for negative index?
/**
* 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)
相关问题:
- 为什么
java.util.ArrayList
中的 rangeCheckForAdd
方法检查负索引?
- 为什么
java.util.Arrays.ArrayList
不进行索引越界检查?
令我困惑的是为什么他们的实现不一致?这些方法是由不同的人用自己的编程风格编写的吗?换句话说,如果越界异常最终会触发,那么就不需要检查了。
这是一个 micro-optimization。为了代码清晰,您可能希望两者使用相同的异常,但是当您处于热循环中时,您会希望避免不必要的操作。 ArrayList
作为一个旧的 class,其影响可能因时间和 JDK 版本而异。如果有人有足够的兴趣,他们可以用 1.8 和更新的 JDKs 对其进行基准测试,以查看它对 get()
.
的优化程度
由于访问负数数组索引无论如何都会失败,因此无需检查它。但是 ArrayList
的大小并不总是与其内部数组的大小相同,因此需要明确检查。
至于为什么 rangeCheckForAdd
检查负索引,问得好。无论如何添加都很慢,所以 micro-optimization 不会有太大的不同。也许他们想要在此处提供一致的错误消息。
数组访问的范围检查检查数组索引是否在范围 0 <= index < elementData.length
。
对于 java.util.ArrayList
,索引的有效范围仅为 0 <= index < size
,size <= elementData.length
。由于数组访问无法正确检查上限(size
可能小于 elementData.length
),ArrayList
class 必须确保不违反上限。
不需要检查下限,因为下限总是 0
并且在访问 elementData
数组时验证。
为什么 rangeCheckForAdd
检查负索引?
添加元素时,可能需要在添加新元素之前增加 elementData
数组的大小。但是如果索引无效(负数或大于大小),您不想增加 elementData
数组。因此,在这种情况下,有必要在执行任何其他操作之前进行完整的边界检查 (0 <= index <= size
)。
为什么java.util.Arrays.ArrayList
不进行越界检查?
java.util.Arrays.ArrayList
的大小恰好是后备数组的大小。因此不需要单独的边界检查(如 java.util.ArrayList
中的那样,其中大小可以小于支持数组的大小)。
/**
* 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)
相关问题:
- 为什么
java.util.ArrayList
中的rangeCheckForAdd
方法检查负索引? - 为什么
java.util.Arrays.ArrayList
不进行索引越界检查?
令我困惑的是为什么他们的实现不一致?这些方法是由不同的人用自己的编程风格编写的吗?换句话说,如果越界异常最终会触发,那么就不需要检查了。
这是一个 micro-optimization。为了代码清晰,您可能希望两者使用相同的异常,但是当您处于热循环中时,您会希望避免不必要的操作。 ArrayList
作为一个旧的 class,其影响可能因时间和 JDK 版本而异。如果有人有足够的兴趣,他们可以用 1.8 和更新的 JDKs 对其进行基准测试,以查看它对 get()
.
由于访问负数数组索引无论如何都会失败,因此无需检查它。但是 ArrayList
的大小并不总是与其内部数组的大小相同,因此需要明确检查。
至于为什么 rangeCheckForAdd
检查负索引,问得好。无论如何添加都很慢,所以 micro-optimization 不会有太大的不同。也许他们想要在此处提供一致的错误消息。
数组访问的范围检查检查数组索引是否在范围 0 <= index < elementData.length
。
对于 java.util.ArrayList
,索引的有效范围仅为 0 <= index < size
,size <= elementData.length
。由于数组访问无法正确检查上限(size
可能小于 elementData.length
),ArrayList
class 必须确保不违反上限。
不需要检查下限,因为下限总是 0
并且在访问 elementData
数组时验证。
为什么 rangeCheckForAdd
检查负索引?
添加元素时,可能需要在添加新元素之前增加 elementData
数组的大小。但是如果索引无效(负数或大于大小),您不想增加 elementData
数组。因此,在这种情况下,有必要在执行任何其他操作之前进行完整的边界检查 (0 <= index <= size
)。
为什么java.util.Arrays.ArrayList
不进行越界检查?
java.util.Arrays.ArrayList
的大小恰好是后备数组的大小。因此不需要单独的边界检查(如 java.util.ArrayList
中的那样,其中大小可以小于支持数组的大小)。