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

Java ArrayList无法保留Table对象不同状态的问题排查

问题原因分析

你的代码核心问题是对象引用复用,以及状态回滚的逻辑错误:

  • 所有列表元素指向同一个Table实例:你执行moves.add(this)时,并没有创建当前Table状态的副本,而是把当前Table对象的引用添加到列表里。整个moves列表里的所有元素其实都是同一个对象的引用,后续对this的任何修改(包括恢复初始位置)都会影响列表里的所有"元素"。
  • 状态回滚逻辑覆盖了已保存的引用:循环中你修改cube位置验证合法后,调用this.setCubes(currentTable)(currentTable是原状态引用,且你已修改其中的cube对象),然后添加this到列表。但后续循环会把cube位置恢复为backupX和backupY——因为所有列表元素都指向同一个this对象,最终所有元素的状态都会被重置为初始状态。
  • 循环内print能显示不同状态是时机问题:循环内的moves.get(0).printTable()是在修改cube位置还没恢复时执行的,此时this是刚修改后的状态;但循环结束后所有cube都恢复到初始位置,此时访问列表任意索引,都是指向已恢复初始状态的this对象,所以只能打印初始状态。
修复方案

要解决问题,你需要为每个合法移动状态创建Table对象的深拷贝,而非复用同一个对象引用:

  1. 实现Table的拷贝构造函数
    给Table类添加拷贝构造函数,复制当前Table的所有状态(包括Cube对象的深拷贝,避免共享Cube引用):

    public Table(Table other) {
        this.K = other.getK();
        // 深拷贝Cube列表
        this.cubes = new ArrayList<>();
        for (Cube cube : other.getCubes()) {
            // 假设Cube有拷贝构造函数,复制ID和位置
            this.cubes.add(new Cube(cube.getId(), cube.getPosX(), cube.getPosY()));
        }
    }
    
  2. 修改generateMoves方法逻辑
    验证到合法移动时,创建当前状态的Table副本添加到列表,再恢复原cube位置:

    public ArrayList<Table> generateMoves(){
        ArrayList<Table> moves = new ArrayList<Table>();
        ArrayList<Cube> currentTable = this.getCubes();
        int K = this.getK();
    
        for(Cube cube : currentTable){
            int backupX = cube.getPosX();
            int backupY = cube.getPosY();
    
            for(int Y = 1; Y <= 3; Y++){
                for(int X = 1; X <= 4*K; X++){
                    // 跳过原位置,避免生成重复状态
                    if (X == backupX && Y == backupY) {
                        continue;
                    }
                    cube.setPosX(X);
                    cube.setPosY(Y);
                    if(cube.isValid(currentTable) && cube.isFree(currentTable)){
                        // 创建当前状态的深拷贝并添加到列表
                        Table newTable = new Table(this);
                        moves.add(newTable);
                    }
                    // 恢复cube原位置
                    cube.setPosX(backupX);
                    cube.setPosY(backupY);
                }
            }
        }
    
        // 此时打印列表元素,每个都是独立状态
        for (Table table : moves) {
            table.printTable();
        }
    
        return moves;
    }
    
  3. 确保Cube对象的深拷贝
    给Cube类也实现拷贝构造函数,避免不同Table实例共享同一个Cube对象,防止修改一个Table的Cube影响其他Table。

内容的提问来源于stack exchange,提问作者Stelios P.98

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 18:07:09