Java固定长度循环触发ArrayIndexOutOfBoundsException问题求助
首先,咱们直接定位问题根源:你遇到的ArrayIndexOutOfBoundsException: length=128; index=128,是因为代码中计算的x值超出了bytes数组的有效索引范围——bytes数组长度是128,所以合法索引是0到127,但你的计算逻辑会让x等于128,直接触发越界。
问题分析
看你循环里的这行代码:
int x = (int) Math.ceil(i * 8.5);
当i=15时,15*8.5=127.5,Math.ceil()会把它向上取整为128,这时候访问bytes[128]就触发了异常。而且随着i增大,x会远大于127,问题会持续出现。你之前修改循环次数(改成128或者i<=120)完全没触碰到这个核心问题,所以当然没用。
另外,你的points数组初始化逻辑也有隐患:
if (points == null || points.length < bytes.length * 4) { points = new float[bytes.length * 4]; }
你循环要生成120组数据(每组4个float),也就是需要120*4=480个元素。如果bytes.length*4小于480(比如bytes长度小于120),后续给points[i*4+3]赋值时也会触发越界。
解决方案
1. 修正x的计算逻辑,确保不超出bytes的索引范围
我们需要把120个循环的i值,均匀映射到bytes数组的0到127索引上,而不是用固定的8.5乘数。可以用线性映射的方式:
int x = (int) Math.round(i * (bytes.length - 1) / 119.0);
或者用Math.min兜底,防止意外越界:
int x = Math.min((int) Math.ceil(i * (bytes.length - 1) / 119.0), bytes.length - 1);
这样i从0到119时,x会从0平滑过渡到127,完全不会超出bytes的合法索引范围。
2. 修正points数组的初始化逻辑
既然你固定要生成120组数据,就应该直接根据循环次数来初始化points,而不是依赖bytes的长度:
if (points == null || points.length < 120 * 4) { points = new float[120 * 4]; }
这样不管bytes长度是多少,points都能容纳所有循环生成的元素。
修改后的完整onDraw关键代码片段
@Override protected void onDraw(Canvas canvas) { if (radius == -1) { radius = getHeight() < getWidth() ? getHeight() : getWidth(); radius = (int) (radius * 0.65 / 2); double circumference = 2 * Math.PI * radius; paint.setStrokeWidth((float) (circumference / 120)); circlePaint.setStyle(Paint.Style.STROKE); circlePaint.setStrokeWidth(4); } circlePaint.setColor(color); canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, circlePaint); if (bytes != null) { // 修正points数组初始化逻辑 if (points == null || points.length < 120 * 4) { points = new float[120 * 4]; } double angle = 0; for (int i = 0; i < 120; i++, angle += 3) { // 修正x的计算逻辑,映射到bytes的合法索引 int x = (int) Math.round(i * (bytes.length - 1) / 119.0); int t = ((byte) (-Math.abs(bytes[x]) + 128)) * (canvas.getHeight() / 4) / 128; points[i * 4] = (float) (getWidth() / 2 + radius * Math.cos(Math.toRadians(angle))); points[i * 4 + 1] = (float) (getHeight() / 2 + radius * Math.sin(Math.toRadians(angle))); points[i * 4 + 2] = (float) (getWidth() / 2 + (radius + t) * Math.cos(Math.toRadians(angle))); points[i * 4 + 3] = (float) (getHeight() / 2 + (radius + t) * Math.sin(Math.toRadians(angle))); } canvas.drawLines(points, paint); } super.onDraw(canvas); }
额外建议
你添加的try-catch虽然能避免崩溃,但会让部分数据无法生成,导致可视化效果异常。修复上述两个问题后,完全可以移除这个try-catch块,让代码更干净。
内容的提问来源于stack exchange,提问作者Ankit Suda

