在 Java 对象中克隆属性相同的对象

Cloning in Java object that got in attribute the same object

我读过这个主题:http://howtodoinjava.com/2012/11/08/a-guide-to-object-cloning-in-java/

我已经做了一些测试并且它有效。现在,我的问题是克隆一个对象 A,它获得了其他对象 A 的列表。例如:

        public class Cell {
            Cell[] listOfCells;
        }

我在 class Cell 中尝试了以下代码:

        public Object clone() throws CloneNotSupportedException {
            Cell cloned = (Cell) super.clone();

            /* Cloning the list.
             * For example, trying to clone the first cell of the list.
             */
            Cell[] clonedList = new Cell[listOfCells.length];
            clonedList[0] = (Cell) listOfCells[0].clone();
        }

问题是,当调用该列表上的方法时,每个单元格将再次调用该方法等等,然后,Whosebug。

编辑:@PaulBoddington 是的,我正在尝试深拷贝。是的,listOfCells 将包含 this(间接)。简而言之,每个单元格都有一些我用列表表示的邻居(它们是单元格)。我想要实现的是:克隆一个细胞并通过修改这个克隆,它不会影响原来的。例如:

    Cell original;
    Cell cloned = original.clone();

    cloned.die();
    cloned.listOfCells[0].die(); // the first neighbor of the clone

    cloned.showState(); // display dead
    cloned.listOfCells[0].showState; // display dead

    original.showState(); // display alive
    original.listOfCells[0].showState(); // the first neighbor of the original, must be alive

在你的 clone() 方法中替换行

 clonedList[0] = (Cell) listOfCells[0].clone();

for (int i = 0; i < listOfCells.length; i++) {
   Cell clone = this;
   if (listOfCells[i] != this) { // avoid endless loop in case of self reference
      clone = (Cell) listOfCells[i].clone();
   }
   clonedList[i] = clone;
}

我会避免 cloneclone 被广泛认为已损坏(参见例如 Joshua Bloch 的 Effective Java,或搜索此站点)。相反,您可以编写自己的方法。

我写了一个我认为可行的方法 deepCopy。它使用 IdentityHashMap 来发现先前遇到的 Cell 以避免多次计算其副本。

请注意,此方法仍然是递归的,因此对于非常非常大的结构,无论如何您都会遇到 WhosebugErrors,但是对于可以直接或间接包含自身的对象,没有办法做到这一点使用类似这样的东西。

// My answer assumes there is a constructor like this.
public Cell(int i) {
    listOfCells = new Cell[i];
}

public Cell deepCopy() {
    return deepCopy(this, new IdentityHashMap<Cell, Cell>());
}

private static Cell deepCopy(Cell original, Map<Cell, Cell> map) {
    if (original == null)
        return null;
    Cell copy = map.get(original);
    if (copy != null)
        return copy;
    int length = original.listOfCells.length;
    copy = new Cell(length);
    map.put(original, copy);
    for (int i = 0; i < length; i++)
        copy.listOfCells[i] = deepCopy(original.listOfCells[i], map);
    return copy;
}