You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX国际象棋棋子移动报错:ConcurrentModificationException原因排查

解决JavaFX移动棋子时的ConcurrentModificationException问题

这个ConcurrentModificationException我在JavaFX开发里也碰到过,根源很简单:你在遍历GridPane的子节点列表的同时,直接修改了这个列表的结构(调用gridPane.getChildren().remove(node))。

Java的集合迭代器有个「快速失败」机制:当迭代器正在遍历集合时,如果集合被迭代器之外的操作修改了(比如直接调用集合的remove/add方法),迭代器就会抛出这个异常来阻止潜在的错误行为。你用的增强for循环底层依赖的就是迭代器,所以在循环里删元素肯定会触发这个问题。

怎么修复?

给你两种靠谱的解决方案:

方案1:使用迭代器的remove()方法替换直接删除

迭代器自己的remove()方法会同步更新迭代器的内部状态,不会触发并发修改检测:

public void MovePawn(GridPane gridPane, int col, int row) {
    int co = 0; // 用来跳过棋盘上方的第一个匹配节点
    Iterator<Node> iterator = gridPane.getChildren().iterator();
    
    while (iterator.hasNext()) {
        Node node = iterator.next();
        if (GridPane.getColumnIndex(node) == col && GridPane.getRowIndex(node) == row) {
            if (co == 1) {
                // 用迭代器的remove方法删除,安全不抛异常
                iterator.remove();
                gridPane.add(this.IMG, this.x, this.y + 2);
            }
            co = 1;
        }
    }
}

方案2:先收集要删除的节点,遍历完成后再统一处理

这种方式更直观,尤其适合需要批量删除的场景,先把要删的节点记下来,等遍历完再操作集合:

public void MovePawn(GridPane gridPane, int col, int row) {
    int co = 0;
    Node targetNode = null; // 存储要删除的目标节点
    
    // 先遍历,只收集目标,不修改集合
    for (Node node : gridPane.getChildren()) {
        if (GridPane.getColumnIndex(node) == col && GridPane.getRowIndex(node) == row) {
            if (co == 1) {
                targetNode = node;
            }
            co = 1;
        }
    }
    
    // 遍历结束后再修改集合
    if (targetNode != null) {
        gridPane.getChildren().remove(targetNode);
        gridPane.add(this.IMG, this.x, this.y + 2);
    }
}

额外提一句

你的co变量逻辑是为了跳过棋盘上方的第一个匹配节点对吧?这个思路没问题,但要确保计数逻辑和你的UI层级对应,避免误删或者漏处理节点哦。

内容的提问来源于stack exchange,提问作者xCrazy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:28:23