防范索引越界需前置校验动态索引:①用户输入、split结果、取模运算、偏移计算均须显式验证;②负数取模应修正为非负;③多线程下需同步或改用线程安全结构。

防范索引计算越界,关键不是等异常发生再捕获,而是让非法索引根本没机会参与数组访问——所有动态算出来的下标,都必须在使用前落地校验。
动态索引必须显式校验
从用户输入、字符串分割、数学运算或外部接口得来的索引,一律不可信。哪怕公式看起来“不会越界”,也要按实际值检查。
- split()结果可能为空:String[] parts = s.split(","); if (parts.length > 0) { String first = parts[0]; },否则直接取
[0]必崩 - 取模运算不保安全:arr[i % arr.length]看似稳妥,但若
i是负数,i % arr.length仍可能为负——应改用((i % arr.length) + arr.length) % arr.length或先判断符号 - 偏移类计算要整体验证:比如
int targetIdx = baseIdx + offset,不能只查baseIdx或offset单独合法,而要验证targetIdx >= 0 && targetIdx
循环边界严守“小于长度”原则
for 循环是最易出错的场景,错误往往藏在终止条件里。
- 数组遍历必须写成
i ,写成<code>i 或<code>i 都会在最后一轮触发越界 - 反向遍历时起点是
arr.length - 1,不是arr.length - 配对操作(如比较相邻元素)时,上限设为
arr.length - 1,避免arr[i+1]越界 - 嵌套循环中,内层上限若依赖外层变量(如
for (int j = 0; j ),需确认<code>i本身未超arr.length
优先绕开索引,用更安全的遍历方式
不需要下标时,就彻底放弃索引管理——这是零成本、零风险的防御。
- 纯读取遍历一律用增强 for:
for (String s : arr),JVM 自动控制边界 - 需要索引又想省心?改用
List配合list.size()和list.get(i),语义清晰且工具链支持更好 - 流式操作替代手动索引:如取第 n 个元素,可用
list.stream().skip(n).findFirst(),内部已做边界防护
空数组和 null 引用必须同步检查
越界异常常被误判,其实真正抛出的是NullPointerException——因为数组引用本身就是null。
- 校验顺序要合理:先判
arr != null,再判index >= 0 && index - 框架返回的数组(如 MyBatis、JSON 解析)极易为空,不能仅靠
instanceof Object[]就认为安全 - 多线程环境下,即使检查了
arr.length > index,另一线程也可能在执行前将数组重置为new String[0]——必要时加同步或换用线程安全结构











