为什么Java两层while循环需重复编写数组长度边界判断条件?
数组下标越界原因说明
用于统计数组中最大连续1个数的两层while循环实现代码如下:
public int findMaxConsecutiveOnes(int[] nums) { int maximum = 0; int i = 0; while (i < nums.length) { int conOnes = 0; while (i < nums.length && nums[i] == 1) { conOnes++; i++; } maximum = Math.max(maximum, conOnes); i++; } return maximum; }
你认为外层循环已经写了i < nums.length判断,内层不需要重复加边界校验,这个想法的漏洞在于:外层循环的边界判断只在每轮外层循环刚启动时执行一次,进入循环体后,不会实时拦截i的越界递增。
我们拿触发报错的典型场景——长度为6、所有元素都是1的数组举例,走一遍删掉内层边界判断后的执行流程,就能直接看到问题:
- 外层循环启动时i=0,满足
0 < 6的条件,顺利进入外层循环体 - 进入内层循环,此时内层仅判断
nums[i] == 1:- i从0开始逐次自增,连续统计连续1的个数;当i=5(数组最后一个合法下标)时,判断nums[5]等于1,conOnes计数加1,随后执行
i++,i的值变成6 - 内层循环会再次执行条件判断,尝试访问
nums[6],但长度为6的数组合法下标范围是0~5,下标6已经越界,直接抛出ArrayIndexOutOfBoundsException
- i从0开始逐次自增,连续统计连续1的个数;当i=5(数组最后一个合法下标)时,判断nums[5]等于1,conOnes计数加1,随后执行
- 整个过程中i增长到6的动作发生在内层循环里,此时还没走到外层循环的下一轮条件判断,自然不会被外层的边界校验拦住。
补充说明:当前代码即使保留内层的边界判断,在内层循环结束后固定执行的
i++,在遇到数组末尾是连续1的场景时会多做一次无意义的i自增,只是因为下一轮外层循环会校验i的大小,不会触发报错,也不影响最终返回结果。
内容的提问来源于stack exchange,提问作者Yun
相关产品推荐
相关产品推荐

