从两个可填充EditText列表取值计算时遇IndexOutOfBoundsException求助
嘿,我来帮你搞定这个越界异常!首先,IndexOutOfBoundsException 本质就是你尝试访问列表/数组里不存在的索引位置,咱们从你贴的代码里揪出几个关键问题:
核心问题:列表长度不匹配导致越界
看这段代码:
// 这里只循环到scoreList和totalList中较短的那个长度 for (int x = 0; x < scoreList.size()&& x<totalList.size(); x++) { CalculateActivity.this.gradesList.add(scoreList.get(x) / totalList.get(x)); } // 但这里直接用coursesList的长度来遍历gradesList! for (int i = 0; i < CalculateActivity.this.coursesList.size(); i++) { int crdtHrs = ((Course) CalculateActivity.this.coursesList.get(i)).getCreditHours(); totalCrdtHrs += (float) crdtHrs; // 这里如果i >= gradesList.size(),就会直接抛出越界异常! averageGrade += (((Float)CalculateActivity.this.gradesList.get(i).floatValue())*(((Course) CalculateActivity.this.coursesList.get(i)).getCredit...
如果coursesList的元素数量比gradesList多(毕竟gradesList的长度是scoreList和totalList中较小的那个),当循环到i超过gradesList的最大索引时,自然就会抛出异常。
具体修复方案
1. 确保三个核心列表长度严格一致
每个课程(coursesList里的元素)必须对应一个分数(scoreList)和一个总分(totalList),这是前提!在从EditText获取数值添加到列表时,要保证每添加一个Course到coursesList,就同步添加对应的分数和总分到另外两个列表,不能出现漏加或者多加的情况。
2. 添加输入校验,避免无效数据导致列表长度异常
用户可能会输入空值或者非数字内容,这会导致你无法正常添加数据到scoreList/totalList,进而破坏三个列表的对应关系。给EditText的取值逻辑加个校验:
// 示例:从某个课程对应的EditText获取分数和总分 EditText scoreInput = findViewById(...); EditText totalInput = findViewById(...); String scoreText = scoreInput.getText().toString().trim(); String totalText = totalInput.getText().toString().trim(); // 先判断非空,再尝试转成数字 if (!scoreText.isEmpty() && !totalText.isEmpty()) { try { float score = Float.parseFloat(scoreText); float total = Float.parseFloat(totalText); // 校验通过才添加到列表 scoreList.add(score); totalList.add(total); } catch (NumberFormatException e) { // 提示用户输入合法数字 Toast.makeText(this, "请输入有效的数字分数", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "分数和总分不能为空", Toast.LENGTH_SHORT).show(); }
3. 修复循环逻辑,避免索引越界
在计算averageGrade的循环里,要么用gradesList.size()作为循环上限,要么加个索引判断:
// 方案一:用gradesList的长度作为循环上限(前提是三个列表长度一致) for (int i = 0; i < CalculateActivity.this.gradesList.size(); i++) { Course course = CalculateActivity.this.coursesList.get(i); int crdtHrs = course.getCreditHours(); totalCrdtHrs += (float) crdtHrs; // 这里可以简化代码,gradesList存的是Float,直接get(i)就能用 averageGrade += (CalculateActivity.this.gradesList.get(i) * crdtHrs); } // 方案二:加索引安全判断(兼容列表长度不一致的临时场景) for (int i = 0; i < CalculateActivity.this.coursesList.size(); i++) { if (i >= CalculateActivity.this.gradesList.size()) { // 跳过当前不匹配的项,避免越界 continue; } Course course = CalculateActivity.this.coursesList.get(i); int crdtHrs = course.getCreditHours(); totalCrdtHrs += (float) crdtHrs; averageGrade += (CalculateActivity.this.gradesList.get(i) * crdtHrs); }
4. 每次计算前清空gradesList
每次点击calculate按钮时,记得先清空gradesList,不然每次计算都会往里面追加新元素,导致列表长度越来越乱:
public void onClick(View view) { float gradePointsCalc = 0.0f; float totalCrdtHrs = 0.0f; // 先清空旧的计算结果 CalculateActivity.this.gradesList.clear(); // 然后再执行后续的计算逻辑... }
额外优化建议
你代码里的((Float)gradesList.get(i).floatValue())有点冗余,因为gradesList的泛型是Float,直接gradesList.get(i)就能拿到float类型的值,不需要额外强转和调用floatValue()。
按照上面的步骤调整后,应该就能解决IndexOutOfBoundsException的问题,同时也能保证代码的运行逻辑更稳定~
内容的提问来源于stack exchange,提问作者Junseok Joon Kang

