java - 包含 java 中对象的二维数组的深拷贝未按预期工作

标签 java arrays clone

这是对以前帖子的重写。我现在编写了一个完整的新项目只是为了展示我不理解的行为。下面你可以看到代码。该问题在本文末尾的测试输出中变得明显。我的假设是错误位于标记为/* PROBLEMATIC */的行,但我不知道这是怎么错误的。

我想做的是:

  • 创建一个棋盘对象boardA

  • 创建另一个名为 boardB 的板,它是 boardA 的深拷贝,因此它引用其数组 pos[][] 中的不同 Square 对象(正如输出告诉我的那样,它确实如此)。

因此,当我输出对象 ID(使用 hashCode())(就像在第二个 Board 复制构造函数中一样)时,我希望为每个对象获得不同的哈希值(我确实得到了),并且为每个 Square 对象的父对象获得不同的哈希值(我没有)。我希望输出能够澄清这一点。

有什么想法吗? 谢谢。

这是完整的测试代码:

public class CloneTest {

    public static void main(String[] args) {
        Board boardA = new Board();
        Board boardB = new Board(boardA.pos);

        System.out.println("boardA=" + boardA.hashCode());
        System.out.println("boardB=" + boardB.hashCode());
    }

}

class Board {
    final int boardSize = 2;
    Square[][] pos;

    /* create empty board */
    public Board() {
        pos = new Square[boardSize][boardSize];
        for(int row=0; row < boardSize; row++)
            for(int col=0;col < boardSize; col++) {
                pos[row][col] = new Square(row,col);
            }
    }

    /* copy existing board */
    public Board(Square[][] initpos) {
        pos = new Square[boardSize][boardSize];

        for(int row=0; row < boardSize; row++)
            for(int col=0;col < boardSize; col++) {

                System.out.println("initpos["+row+"]["+col+"]=" + initpos[row][col].hashCode() + 
                        " gh=" + initpos[row][col].gameHash());

                try {
                    this.pos[row][col] = initpos[row][col].clone(); /* PROBLEMATIC? */
                } catch (CloneNotSupportedException e) {
                }

                System.out.println("this.pos["+row+"]["+col+"]=" +  this.pos[row][col].hashCode() + 
                        " gh=" + this.pos[row][col].gameHash());

            }
    }

    class Square implements Cloneable {
        int row;
        int col;

        public Square(int r, int c) {
            row = r;
            col = c;
        }

        public Square clone() throws CloneNotSupportedException {
            Square newsquare = (Square) super.clone(); /* WRONG?*/
            return newsquare;
        }

        public int gameHash() {
            return Board.this.hashCode();
        }
    }
}
<小时/>

这是一个示例输出:

initpos[0][0]=1598553873 gh=1874519541
this.pos[0][0]=1464824097 gh=1874519541
initpos[0][1]=546069071 gh=1874519541
this.pos[0][1]=1585252666 gh=1874519541
initpos[1][0]=1659432780 gh=1874519541
this.pos[1][0]=716609871 gh=1874519541
initpos[1][1]=973809521 gh=1874519541
this.pos[1][1]=843745660 gh=1874519541
boardA=1874519541
boardB=998786479

如您所见,initpos[0][0] 和 this.pos[0][0] 行的 gh 值相同 (1874519541)。 我预计 this.pos[0][0] 的 gh 值为 998786479,这是 boardB 的 id。

所以克隆的 Square 对象(它应该有一个不同的 id)仍然认为它属于第一个 Board 对象。但既然我将它分配给构造函数内的新 Board 对象,那怎么可能呢?

最佳答案

Java 的 clone() 很棘手(如果不是邪恶的话),对于内部类更是如此。

我认为this适用:

The "proper" way is to define the clone method of the inner class with an argument of enclosing class.

或者更好的是,忘记克隆并编写复制构造函数。

关于java - 包含 java 中对象的二维数组的深拷贝未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20442263/

相关文章:

c - 如何在标准 C 中创建一个新的 char*

javascript - 用 JQuery 替换 $j

java - JFrame如何自行刷新?

java - 访问网络状态时出错

ios - 如何根据数组中包含的字符串隐藏特定的 UIButton

Java,对 double 组及其索引进行排序

java - 如何保护 REST API 中的输入 JSON 对象?

java - 在被调用方法内分配一个对象,将其作为参数传递后,对调用方法没有任何影响

jquery - 如何使用 jQuery 克隆表中的两列

java - 实现克隆功能