IndexOutOfBoundsException 是抽象父类,不直接抛出;实际抛出的是其子类:ArrayIndexOutOfBoundsException(数组访问)、StringIndexOutOfBoundsException(字符串操作)或 IndexOutOfBoundsException(集合类如 ArrayList)。

IndexOutOfBoundsException 是父类,不是具体错误类型
Java里根本不会直接抛出 IndexOutOfBoundsException 这个“裸异常”——它只是个抽象基类,所有索引越界问题都由它的子类实际承担。你看到的报错信息里写的永远是 ArrayIndexOutOfBoundsException 或 StringIndexOutOfBoundsException 或 IndexOutOfBoundsException(来自 ArrayList、LinkedList 等集合),但背后机制完全不同。
-
ArrayIndexOutOfBoundsException:只发生在原生数组访问时,比如arr[5]而arr.length == 5(合法索引是0–4) -
StringIndexOutOfBoundsException:只出现在对String调用charAt()、substring()等方法时传了非法索引 - 集合类(如
ArrayList.get(i))抛的是IndexOutOfBoundsException本身——因为List接口不绑定数组实现,JDK 直接 throw newIndexOutOfBoundsException
为什么 ArrayList 抛 IndexOutOfBoundsException,而数组抛 ArrayIndexOutOfBoundsException
这是设计意图差异:数组是语言级结构,越界属于底层内存访问违规,需要更具体的异常来区分场景;而 ArrayList 是泛型容器,它的“越界”语义是逻辑层面的——哪怕底层用数组存,对外暴露的仍是“列表索引有效性”问题,和数组物理边界无关。
- 写
list.get(10)时,list.size() == 3→ 抛IndexOutOfBoundsException: Index 10 out of bounds for length 3 - 写
arr[10]时,arr.length == 3→ 抛ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 3 - 两者错误信息格式高度相似,但 JVM 内部处理路径不同,catch 时不能混用——想捕获所有越界,得同时写两个
catch块,或只 catch 父类IndexOutOfBoundsException
别在循环里写 i
几乎所有新手在遍历 List 时栽在这儿:用 for (int i = 0; i ,结果最后一次迭代执行 <code>list.get(list.size()),必然越界。因为合法最大索引是 size() - 1,不是 size()。
- 正确写法只有两种:
i (推荐),或用增强 for 循环(<code>for (String s : list))彻底避开索引 - 如果必须用索引(比如要同时操作前后元素),记得检查边界:
if (i + 1 - 注意:空集合时
list.size() == 0,此时list.get(0)也会越界——别假设非空就安全
捕获时该 catch 哪个?看你的代码到底碰了什么
如果你只操作 ArrayList 和 String,那 catch IndexOutOfBoundsException 就够了(它能覆盖 StringIndexOutOfBoundsException,因为后者也继承自它)。但一旦涉及原生数组,或者用了第三方库返回原始数组(比如某些 NIO buffer 的 array() 方法),就必须考虑 ArrayIndexOutOfBoundsException 是否可能被抛出。
立即学习“Java免费学习笔记(深入)”;
- 通用兜底:用
catch (IndexOutOfBoundsException e)可捕获全部子类,适合日志记录或用户提示 - 精准处理:比如你想对数组越界做降级(返回默认值),对字符串越界做截断,则需分开 catch:
catch (ArrayIndexOutOfBoundsException e)和catch (StringIndexOutOfBoundsException e) - 注意:
catch (RuntimeException e)虽然也能抓到,但太宽泛,会吞掉NullPointerException等真正该暴露的问题
真实项目里最麻烦的,是那种封装了数组访问的工具方法——表面看参数是 List,内部却偷偷调了 toArray() 再按索引取,这时候越界类型就从 IndexOutOfBoundsException 变成了 ArrayIndexOutOfBoundsException,调试时容易漏掉这一层转换。










