Java数组下标从0开始,最大合法下标为arr.length-1;arr[arr.length]越界导致ArrayIndexOutOfBoundsException。常见错误是循环条件写成i<=arr.length。

Java 数组下标从 0 开始,但很多人写 arr[arr.length] 就崩了
数组长度是 arr.length,但最大合法下标是 arr.length - 1。写成 arr[arr.length] 是最常见越界原因,JVM 直接抛 ArrayIndexOutOfBoundsException,不给任何商量余地。
常见错误现象:
- 循环写成
for (int i = 0; i (多跑一次) - 用
Scanner读入n个数后,误以为下标范围是1..n,直接访问arr[n] - 递归或嵌套逻辑里,下标计算没减 1,比如
process(arr, start, end)中把end当作闭区间末尾却没校验
遍历数组时,for-each 能避开越界,但换不了索引操作
for (int x : arr) 确实不会触发 ArrayIndexOutOfBoundsException,因为它不暴露下标。但一旦你需要改某个位置的值、记录位置、做相邻元素比较(比如找峰值),它就无能为力。
使用场景判断:
立即学习“Java免费学习笔记(深入)”;
- 只读 + 不关心位置 → 安全首选
for-each - 要改
arr[i]、要算i+1或i-1、要返回下标 → 必须用传统for (int i = 0; i - 别为了“看起来简洁”硬套
for-each,然后又去额外维护一个计数器变量,那反而更容易错
用 Arrays.asList() 包装数组后,get() 仍会越界
Arrays.asList(arr) 返回的是 List 接口实现,但它底层仍绑定原数组,size() 是 arr.length,所以 list.get(arr.length) 依然抛 ArrayIndexOutOfBoundsException(不是 IndexOutOfBoundsException 的子类?不,它就是——JDK 实现里直接委托给数组访问)。
容易踩的坑:
- 误以为转成
List就“安全”了,其实只是多了层接口,底层数组访问没变 - 用
list.subList(0, k)截取后,再对结果调用get(k)(越界),因为subList返回的是视图,长度仍是k,最大下标是k-1 - 和
ArrayList混淆:后者扩容后允许插入,但数组本身不可扩容,Arrays.asList()返回的对象也不支持add()
调试时别只看异常堆栈,重点查 index 值和 array.length
IDE 调试时,ArrayIndexOutOfBoundsException 的消息通常是 Index 5 out of bounds for length 5 —— 这句话已经告诉你:你访问了第 5 号位置(即下标 5),但数组只有 5 个元素,合法下标是 0~4。关键不是“哪行报错”,而是“当时 i 是几?arr.length 是几?”
实操建议:
- 在出问题的访问语句前加一行
System.out.println("i=" + i + ", len=" + arr.length);,比猜快得多 - 如果用 IDE,直接把鼠标悬停在
i和arr.length上看实时值,别跳进循环里单步十次 - 上线后日志里捕获该异常时,务必打印
e.getMessage(),它自带具体数值,比空泛的异常类型有用得多
越界本身很简单,难的是在复杂条件分支、多层嵌套或状态传递中,那个 i 是怎么悄悄变成 arr.length 的。盯住变量值,比盯住语法更重要。










