Java调用FileDealer.modify方法二次执行时indexOf返回-1引发越界异常的解决
问题根因拆解
这个报错本质不是真的数组越界,是indexOf()返回-1后没有做边界校验,直接调用List.get(-1)触发的异常,结合你的代码时序,问题的产生路径非常清晰:
- 程序初始化时,你拿到的
t2是从FileDealer初始加载的ticketList中取出的,和列表内的对象是同一引用 - 第一次调用
modify(t2, 0, "99999")时,因为是同一引用,indexOf()能正常匹配到索引,完成字段修改后,代码会执行updateFile()写回文件,随后无条件调用readFile()——这个方法一般是清空原有ticketList,从磁盘重新读取数据,生成一批全新的Ticket实例塞回列表,此时你原来持有的t2引用已经不在列表内了 - 第二次调用
modify(t2, 0, "88888")时,indexOf()默认使用Object类的equals()方法(本质是比较对象内存地址)做匹配,因为列表里已经是新的Ticket实例,和旧的t2地址不一致,就会返回-1,后续直接调用get(-1)就触发了越界异常
修复方案
1. 为Ticket类重写equals与hashCode方法
不要依赖对象引用做匹配,基于业务上的唯一标识(比如mainID)定义对象相等规则,这样哪怕列表被重新加载,只要字段值匹配就能正常识别:
// 在Ticket类中添加 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Ticket ticket = (Ticket) o; // 用业务唯一字段做匹配,避免非唯一字段导致误匹配 return Objects.equals(mainID, ticket.mainID); } @Override public int hashCode() { return Objects.hash(mainID); }
2. 给index查找结果增加边界校验
拿到索引后先判断有效性,不要直接调用get,避免无意义的底层越界异常,方便定位业务问题:
int index = ticketList.indexOf(t); if (index == -1) { // 直接抛出明确的业务异常,替代底层的数组越界报错 throw new IllegalArgumentException("未在工单列表中匹配到目标工单"); } Ticket toModify = ticketList.get(index);
3. 移除modify方法末尾冗余的readFile调用
你现在每次修改完列表内容、写回文件后,没必要再全量从磁盘重新读一遍列表——既浪费IO性能,又会因为对象重建引发引用匹配问题。内存里的ticketList已经是修改后的最新状态,只需要保留updateFile()做持久化同步即可。
如果确实需要在修改后校验文件内容一致性,也要调整readFile()的逻辑:不要清空整个列表替换对象,改为增量同步字段、保持原有对象引用不变,避免触发匹配问题。
额外优化点
- 当type为4执行删除操作时,不要在remove后继续操作被移除的对象,避免空指针
- 不要提前将
toModify初始化为null,直接在索引校验通过后初始化实例,减少不必要的空指针风险
内容的提问来源于stack exchange,提问作者Ell
相关产品推荐
相关产品推荐

