Objects.checkIndex() 专用于单索引访问前的合法性断言,如 arr[i]、list.get(i)、str.charAt(i);不适用于范围校验(如 subList)或复合计算(如 i + j == 0 && i < n)。

Objects.checkIndex() 适合在哪些地方替代手写 if 判断
它不是万能兜底,而是专用于「单索引访问前的合法性断言」场景:比如 arr[i]、list.get(i)、str.charAt(i) 前。不适合用在范围校验(如 subList(from, to))或复合计算(如 i + j )中——后者该用 <code>Objects.checkFromIndexSize()。
为什么不能直接用 checkIndex(i, arr.length) 替换 if (i >= 0 && i
表面看语义等价,但有三个关键差异:
-
Objects.checkIndex()在越界时抛出的是IndexOutOfBoundsException,且异常消息包含具体 index 和 length,比手写 if +throw new IllegalArgumentException(...)更符合 JVM 标准异常链; - 它不返回布尔值,而是「合法则原样返回 index」,方便链式调用,比如
arr[Objects.checkIndex(i, arr.length)]; - JVM 对
Objects.checkIndex()有内联优化支持(尤其 Java 17+),而手写 if 可能因分支预测失败带来微小开销。
常见误用:把 checkIndex 当成防御性编程的“银弹”
它只做一件事:检查单个索引是否落在 [0, length) 内。以下情况它帮不上忙:
- 空集合或空数组未判空:如果
arr是null,调用Objects.checkIndex(i, arr.length)会先触发NullPointerException,不是IndexOutOfBoundsException; - 多索引协同访问:比如要同时取
arr[i]和arr[i+1],只校验i不够,必须用Objects.checkFromIndexSize(i, 2, arr.length); - 字符串首字符校验:写
if (s.charAt(Objects.checkIndex(0, s.length())) != 'x')看似安全,但若s是null或空串,仍会崩——得先if (s != null && !s.isEmpty())。
和 checkFromIndexSize() 的分工要拎清
当你真正要操作一段连续区域(比如 Arrays.copyOfRange(arr, from, to)),必须用 Objects.checkFromIndexSize(from, size, arr.length),而不是套两次 checkIndex():
错误示范:Objects.checkIndex(from, arr.length); Objects.checkIndex(to - 1, arr.length); —— 没防住 from + size 溢出(例如 from = Integer.MAX_VALUE, size = 1);
正确做法:Objects.checkFromIndexSize(from, size, arr.length),它内部用减法做安全比较,能覆盖算术溢出边界。
这个细节容易被忽略,线上出现负数 index 报错(比如 Index -3 out of bounds for length 5),往往就是用了加法逻辑做范围校验。

















