DefaultListModel移除选中元素触发IndexOutOfBoundsException报错如何解决
问题原因分析
触发异常的根本原因是选中元素被删除后,JList 的选中索引会自动变为 -1,此时会立即触发 ListSelectionListener 的 valueChanged 回调,你的回调方法中没有校验索引合法性,直接用 -1 读取集合元素,最终抛出索引越界异常。
完整执行流程如下:
- 点击移除按钮,读取当前选中索引删除业务数据
- 调用
DefaultListModel.removeElementAt删除列表元素 - 因为被删除的是当前选中元素,JList 自动将选中索引置为
-1,触发选中状态变更事件 valueChanged回调被触发,直接调用getSelectedIndex()拿到-1,用-1访问order.getParts()集合直接抛出越界异常
你之前添加 clearSelection 无效大概率是调用时机错误,在删除 Model 元素之后调用已经无法阻止触发选中变更事件。
可行解决方案
从选中回调合法性校验、删除逻辑执行顺序优化两个维度修改即可解决问题:
1. 给 ListSelectionListener 增加索引合法性校验
新增选中调整状态判断、合法索引判断,无有效选中时直接终止逻辑:
private class listHandler implements ListSelectionListener { @Override public void valueChanged(ListSelectionEvent e) { if (e.getSource() == orderList) { // 跳过选中未完成的事件,且判断选中索引合法再执行后续逻辑 if (e.getValueIsAdjusting() || orderList.getSelectedIndex() == -1) { area.setText(""); // 无选中时清空文本展示 return; } int selectedIdx = orderList.getSelectedIndex(); area.setText(order.getParts().get(selectedIdx).getID()+"\n"+"$"+order.getParts().get(selectedIdx).getPrice()+"\n"+ checkCompatiblity(order.getParts().get(selectedIdx)) ); } } }
2. 优化移除按钮逻辑执行顺序
提前缓存选中索引、先校验合法性,再清除选中状态最后执行删除操作,避免触发无效的选中事件:
private class ButtonHandler implements ActionListener { @Override public void actionPerformed(ActionEvent e) { if(e.getSource()== removeButton){ // 提前缓存选中索引,仅校验合法后执行删除 int selectedIdx = orderList.getSelectedIndex(); if (selectedIdx < 0 || selectedIdx >= defaultOrderList.size()) { return; // 无有效选中直接返回,不执行后续逻辑 } totalPrice -= order.getParts().get(selectedIdx).getPrice(); area.setText(""); order.removeComputerPart(selectedIdx); // 先清除选中再删除Model元素,避免触发无效的选中事件处理 orderList.clearSelection(); defaultOrderList.removeElementAt(selectedIdx); } } }
内容的提问来源于stack exchange,提问作者Madhav
相关产品推荐
相关产品推荐

