在TableModelListener中调用setValue触发StackOverflowError问题求助
解决TableModelListener中调用setValue导致无限循环的问题
问题根源
你遇到的无限循环问题,本质是因为调用setValue(...)方法会触发新的TableModelEvent事件,而这个事件又会被你的TableModelListener捕获,再次执行乘法运算并调用setValue(...),形成了无限递归的循环,最终导致程序抛出异常。
解决方案
要打破这个循环,我们需要在修改表格值的时候临时移除监听器,或者添加判断条件,只在特定情况下执行修改逻辑。下面给你两种可行的实现方式:
方式一:临时移除并重新添加监听器
这种方式简单直接,在执行setValue(...)前先把监听器从模型中移除,修改完成后再加回去,避免触发新的事件:
public void populateTable() { DefaultTableModel employeeModel = (DefaultTableModel) jTable1.getModel(); TableModelListener listener = new TableModelListener() { public void tableChanged(TableModelEvent e) { // 先移除监听器,防止触发新事件 employeeModel.removeTableModelListener(this); Integer totalDue = 0; // 这里写你的乘法运算逻辑 // 示例:假设计算第2列和第3列的乘积,放到第4列 int row = e.getFirstRow(); if (e.getColumn() == 1 || e.getColumn() == 2) { // 只在修改第2、3列时计算 Integer quantity = (Integer) employeeModel.getValueAt(row, 1); Integer price = (Integer) employeeModel.getValueAt(row, 2); totalDue = quantity * price; employeeModel.setValueAt(totalDue, row, 3); } // 重新添加监听器,恢复监听 employeeModel.addTableModelListener(this); } }; employeeModel.addTableModelListener(listener); }
方式二:添加状态标记,跳过递归触发的事件
可以用一个布尔变量标记当前是否正在修改值,当处于修改状态时,直接跳过listener的逻辑:
public void populateTable() { DefaultTableModel employeeModel = (DefaultTableModel) jTable1.getModel(); // 标记是否正在更新表格值 AtomicBoolean isUpdating = new AtomicBoolean(false); employeeModel.addTableModelListener(new TableModelListener() { public void tableChanged(TableModelEvent e) { // 如果正在更新,直接返回,避免循环 if (isUpdating.get()) { return; } Integer totalDue = 0; int row = e.getFirstRow(); if (e.getColumn() == 1 || e.getColumn() == 2) { Integer quantity = (Integer) employeeModel.getValueAt(row, 1); Integer price = (Integer) employeeModel.getValueAt(row, 2); totalDue = quantity * price; // 设置标记为正在更新 isUpdating.set(true); employeeModel.setValueAt(totalDue, row, 3); // 完成后重置标记 isUpdating.set(false); } } }); }
额外提示
- 尽量缩小触发修改的范围:比如只在修改特定列(比如数量、单价列)时才计算总价,避免对无关列的修改触发逻辑,减少不必要的事件。
- 注意空值处理:如果表格单元格可能为空,要先判断
getValueAt的结果是否为null,避免NullPointerException。
内容的提问来源于stack exchange,提问作者geneva monk
相关产品推荐
相关产品推荐

