每秒更新JTable值时偶发NullPointerException异常的解决求助
Java Swing JTable定时更新偶发空指针异常解决方案
根本原因
你遇到的偶发空指针是三个典型的Swing开发错误共同导致的:
- 线程违规操作:Swing的所有UI相关逻辑(包括修改UI绑定的数据模型、触发UI更新)必须运行在AWT事件调度线程(EDT)中。你当前使用的
TimerTask是后台工作线程,直接在该线程中修改表格绑定的数组、触发UI刷新,会导致EDT在绘制单元格的过程中,数据被后台线程中途修改,出现状态不一致,进而触发空指针。 - 错误调用
updateUI():该方法是Swing组件用于响应外观(Look&Feel)变更的专用方法,完全不是用来刷新表格内容的。频繁调用该方法会强制重置组件UI状态,是触发空指针的直接诱因。 - 未使用标准TableModel通知机制:直接修改绑定的二维数组,JTable无法精准感知单元格变更,只能通过全量重绘刷新,效率低且容易出现状态冲突。
修复方案
步骤1:重构表格数据管理逻辑
改用DefaultTableModel管理表格数据,删掉自定义的二维数组和错误的updateUI()调用:
// 改用DefaultTableModel管理数据,header保持你原有的列头定义即可 private DefaultTableModel tableModel = new DefaultTableModel(new Object[6][5], header); private JTable tblProcesses = new JTable(tableModel); public Object getCell(int row, int col) { return tableModel.getValueAt(row, col); } public void setCell(int row, int col, Object object) { // 修改模型后会自动通知JTable仅刷新对应单元格,无需手动调用刷新方法 tableModel.setValueAt(object, row, col); }
步骤2:改用Swing专用定时器
替换TimerTask为javax.swing.Timer,该定时器的回调默认运行在EDT线程,从根源避免线程安全问题:
// 1000为触发间隔,单位毫秒,每秒执行一次 Timer processTimer = new Timer(1000, e -> { for (int i = 0; i < 6; i++) { int currentVal = (int) mainTable.getCell(i, 1); mainTable.setCell(i, 1, currentVal + 1); } }); // 启动定时器 processTimer.start();
如果确实需要保留TimerTask实现,必须将UI操作投递到EDT执行:
TimerTask processTimer = new TimerTask() { @Override public void run() { // 将UI操作投递到EDT线程执行 SwingUtilities.invokeLater(() -> { for (int i = 0; i < 6; i++) { int currentVal = (int) mainTable.getCell(i, 1); mainTable.setCell(i, 1, currentVal + 1); } }); } };
补充注意事项
初始化表格时请提前给第1列所有行设置初始数值(比如0),避免强转int时遇到null触发空指针。
内容的提问来源于stack exchange,提问作者Smooth Researcher
相关产品推荐
相关产品推荐

