如何修复placePlayers方法游标遍历的数组越界及视图残留问题
问题分析与解决建议
核心问题排查
循环未提前终止,资源释放后仍执行后续代码
处理最后一条记录的if(pl == cc)分支中,你已经关闭了数据库连接和游标、返回上一页,但for循环并未终止,会继续执行下一次迭代。此时游标和连接已释放,再访问currentRow或执行cur.next()必然触发索引越界错误。游标操作逻辑错误
- 调用
cur.next()后未更新currentRow = cur.getRow(),后续操作始终使用上一条记录的内容; - 初始获取
currentRow前未判断游标是否为空,若查询无结果会直接报错。
- 调用
视图组件清理不彻底
移除组件后未触发界面重绘,或部分组件移除逻辑遗漏,导致第二次视图名称残留。SQL注入风险(附带问题)
直接拼接字符串生成SQL语句,存在注入漏洞,需改用参数化查询。
具体修复步骤
1. 终止循环,避免资源释放后继续执行
在if(pl == cc)分支最后添加提前返回逻辑,终止后续循环和方法执行:
if (pl == cc) { // ... 原有放置标签、清理组件、关闭资源、返回上页的代码 ... contactEditor.showBack(); // 提前返回,终止方法剩余逻辑 return true; }
2. 修正游标操作逻辑
添加游标空判断,每次cur.next()后更新currentRow:
cur = dbp.executeQuery(rd); // 先判断是否存在有效记录 if(!cur.next()){ dbp.close(); cur.close(); return false; } Row currentRow = cur.getRow(); // ... 原有获取txt、cc、x的代码 ... for (r = 1; r < x; r++) { // ... 原有放置标签、动画等待、移除标签的代码 ... // 移动到下一条记录并更新currentRow if(!cur.next()){ break; } currentRow = cur.getRow(); //Check to determine last record pl = currentRow.getInteger(2); // ... 原有最后记录处理代码 ... } // 确保循环结束后资源被关闭(避免分支中未执行到的情况) if(dbp != null && !dbp.isClosed()){ dbp.close(); } if(cur != null && !cur.isClosed()){ cur.close(); }
3. 完善视图清理,触发界面重绘
移除组件后调用重绘方法,确保界面更新:
//Removing View components so the View form can be redrawn controlarea.removeComponent(add1); controlarea.removeComponent(caLabel); monitor.removeComponent(controlarea); field.removeAll(); gls.removeAll(); monitor.removeComponent(field); monitor.removeComponent(gls); // 触发界面重绘 monitor.revalidate(); monitor.repaint();
4. 修复SQL注入问题
改用参数化查询替换字符串拼接:
String rd = "SELECT * FROM PandR WHERE name = ?"; cur = dbp.executeQuery(rd, namevt);
额外优化建议
- 使用
try-with-resources自动管理数据库资源,避免手动关闭遗漏:
try(DB dbp = Display.getInstance().openOrCreate("pandr.db"); Cursor cur = dbp.executeQuery(rd, namevt)){ // 原有游标处理逻辑 } catch(IOException e){ e.printStackTrace(); return false; }
- 避免使用全局变量(如
dbp、cur、namevt),改为方法内部变量或参数传递,减少状态混乱。
内容的提问来源于stack exchange,提问作者curtjacobs1
相关产品推荐
相关产品推荐

