Java 操作数据时,偶尔会出现异常 ArrayIndexOutOfBoundsException。我们需要了解为什么会出现这个异常,以及如何避免出现这样的异常。
基础回顾
在Java中,数组是一种静态数据结构,我们在创建时就定义了它的大小。
我们使用索引访问数组的元素。数组中的索引从零开始,并且不能大于或等于数组的大小。
经验法则是 0 <= index < size
。
理解 ArrayIndexOutOfBoundsException
ArrayIndexOutOfBoundsException在我们访问一个数组或Collection时发生,该数组由具有无效索引的数组支持。这意味着索引小于零或大于或等于数组的大小。
此外,边界检查发生在运行时,ArrayIndexOutOfBoundsException是一个运行时异常。因此,我们在访问数组的边界元素时需要格外小心。
读取数组元素
访问数组时可能发生的最常见错误是忘记了上限和下限。
数组的下限始终为 0,而上限比其长度小 1。
访问超出这些范围的数组元素会抛出ArrayIndexOutOfBoundsException:
int[] numbers = new int[] {1, 2, 3, 4};
int lastNumber = numbers[4];
这里,数组的大小是 4,这意味着索引的范围是 0 到 3。
在这种情况下,访问第 4 个索引会导致ArrayIndexOutOfBoundsException:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
小于0的数也会出现相同的异常:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -2
读取列表
静态方法 Arrays.asList() 返回一个由指定数组支持的固定大小的列表。此外,它与数组类似,索引从零开始,范围为比其大小少一。
如果我们尝试访问超出此范围的Arrays.asList()返回的List的元素,会得到一个ArrayIndexOutOfBoundsException:
List<Integer> numbersList = Arrays.asList(1, 2, 3, 4);
int lastNumber = numbersList.get(4);
错误边界处理
有时,在 for 循环中迭代数组时,我们可能会输入错误的终止表达式。
我们可能最终迭代直到它的长度,而不是在比数组长度小一的位置终止索引:
int[] numbers = new int[] {1, 2, 3, 4};
int sum = 0;
for (int i = 0; i <= numbers.length; i++) {
sum += numbers[i];
}
for 的退出条件是,循环变量 i
等于或小于数组长度,在遍历的最后一次迭代中, i
为4,超出了数组长度,会导致 ArrayIndexOutOfBoundsException。
如何避免ArrayIndexOutOfBoundsException
既然已经知道了异常是如何产生的,我们需要从下面几个方面去考虑,如何避免在程序中出现 ArrayIndexOutOfBoundsException。
注意索引下标区间
我们必须始终记住,Java 的数组索引从 0 开始。因此,第一个元素始终位于索引 0 处,而最后一个元素位于比数组长度小 1 处的索引处。
使用 forEach
传统的 for 循环存在最后一个数据的边界问题,错误地使用运算符 <、<=、> 或 >= 是发生此异常的常见原因。
因此,我们在遍历数组时,才用增强 for 循环,它不设计索引下标:
for (int number : numbers) {
sum += number;
}
JVM 会正确地处理数组下标,避免出现 ArrayIndexOutOfBoundsException。