绝大多数情况下不应捕获IndexOutOfBoundsException,因其反映编程错误而非正常异常;仅在解析不可控外部输入且业务允许忽略无效索引时才可捕获,切勿用try-catch替代边界检查。

Java数组和List越界时,IndexOutOfBoundsException到底该不该捕获?
绝大多数情况下,IndexOutOfBoundsException是编程错误,不是运行时异常场景,捕获它往往掩盖了真实bug。比如用list.get(5)访问只有3个元素的ArrayList,问题出在调用前没校验索引,而不是“需要兜底”。
- 只在极少数场景下可捕获:解析外部不可控输入(如用户填的下标、配置文件里的索引值),且业务逻辑允许“无效索引=忽略或默认值”
- 不要在循环里用
try-catch代替i ——性能差,语义错,JVM也优化不了 - IDEA或Sonar会警告“catching
IndexOutOfBoundsException”,这不是误报,是提醒你检查边界逻辑
ArrayList.get()和Arrays.asList().get()的边界行为一致吗?
一致。两者都基于数组实现,get(int index)内部都直接做index >= size || index 判断,抛出<code>IndexOutOfBoundsException。但注意:Arrays.asList()返回的是固定大小的List,不支持add()/remove(),越界判断只发生在get()和set()。
-
Arrays.asList(new String[0]).get(0)→ 抛IndexOutOfBoundsException: Index 0 out of bounds for length 0 -
new ArrayList().get(0)→ 抛IndexOutOfBoundsException: Index: 0, Size: 0(消息格式略有不同,但类型相同) - 别依赖错误消息文本做判断,只依赖异常类型——
instanceof IndexOutOfBoundsException才可靠
用Math.min(index, size - 1)代替边界检查安全吗?
不安全,这是典型“用技巧绕过问题”的做法。它把越界读变成读末尾元素,表面不崩溃,实则引入静默错误。
- 比如分页查第100页数据:
list.get(Math.min(pageNo * pageSize, list.size() - 1))→ 实际永远取最后一个元素,业务逻辑全乱 - 如果本意是“越界就返回null”,应该显式写
index >= 0 && index -
Math.min适合做截断(如字符串截取str.substring(0, Math.min(len, str.length()))),不适合替代索引合法性判断
Guava和Apache Commons有没有更安全的集合访问工具?
有,但它们不改变根本逻辑——只是帮你把边界检查写得更简洁,不消除检查本身。
立即学习“Java免费学习笔记(深入)”;
- Guava:
Lists.newArrayList("a", "b").get(5)还是抛异常;但Iterables.getOrDefault(list, 5, "default")可安全返回默认值 - Commons Collections:
CollectionUtils.get(list, 5)返回null(对泛型List<String>可能引发NPE),不如自己写一行三元表达式清晰 - 真正省心的方式是用
Optional封装:写个safeGet(List<T> list, int i)返回Optional.ofNullable(...),调用方明确处理空情况
边界检查不是样板代码,是业务契约的一部分。漏掉i >= 0比漏掉i 更隐蔽,因为负索引在某些语言里合法,在Java里直接崩,而且堆栈看不出是哪层逻辑传进来的负数。










