
ArrayIndexOutOfBoundsException 什么时候抛出
这个异常只在运行时发生,不是编译错误,所以写 arr[100] 不会报错,但执行到那行就崩。常见于循环边界写错、空数组没判空、动态计算索引漏掉 -1。
- 循环用
for (int i = 0; i —— 多走一次,<code>i == arr.length时越界 - 调用
list.get(i)前没确认i ,尤其从外部传入索引时 - 字符串切片
str.substring(5, 10)但str.length() ,第二个参数超长
怎么提前拦住越界访问
靠 try-catch 是下策,既掩盖逻辑问题又影响性能。真正有效的做法是把边界检查写进逻辑里,尤其是索引来源不可信时。
- 数组访问前加判断:
if (i >= 0 && i - 用
Math.min(i, arr.length - 1)或Math.max(0, Math.min(i, arr.length - 1))做安全截断(适合容错场景,比如 UI 滚动位置) - 集合操作优先用增强 for 或迭代器,避开手动索引 ——
for (String s : list)完全规避越界 - 工具类如
Objects.checkIndex(i, arr.length)(Java 9+)可复用标准校验,抛出的异常信息更明确
Arrays.asList() 和原始数组的坑
Arrays.asList(arr) 返回的不是普通 ArrayList,而是内部封装了原始数组的固定大小列表,它的 get(i) 底层仍走原数组索引,但长度不等于 arr.length 的直觉表现。
- 对基本类型数组(如
int[])调用Arrays.asList(intArr),结果是包含一个int[]元素的列表,size()是 1,不是元素个数 - 修改返回列表的元素(如
list.set(0, "x"))会直接改原数组;但add()或remove()会抛UnsupportedOperationException,和越界无关但容易混淆 - 真要转成可操作的
ArrayList,得写new ArrayList(Arrays.asList(...)),且确保传入的是对象数组(如String[])
调试时怎么看清越界源头
堆栈里只显示 ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5,但你得知道 5 是哪来的。别急着改数字,先定位索引生成逻辑。
立即学习“Java免费学习笔记(深入)”;
- 在可疑索引变量赋值处打条件断点,比如
i = someCalculation();这行,看它怎么算出 5 - 日志里别只打
arr[i],改成log.debug("accessing arr[{}] with length {}", i, arr.length) - 如果索引来自用户输入或配置文件,立刻加校验:小于 0?大于等于长度?是否为 null?
- 静态分析工具如 SpotBugs 能检出部分明显越界模式(如恒定超限的常量索引),但对动态计算无能为力
实际中最容易被忽略的,是把「数组长度」和「有效数据长度」当成一回事 —— 比如缓存数组预留空间但只用了前几个元素,这时候 arr.length 不代表可用范围。









