在 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;
}
我会避免 clone
。 clone
被广泛认为已损坏(参见例如 Joshua Bloch 的 Effective Java,或搜索此站点)。相反,您可以编写自己的方法。
我写了一个我认为可行的方法 deepCopy
。它使用 IdentityHashMap
来发现先前遇到的 Cell
以避免多次计算其副本。
请注意,此方法仍然是递归的,因此对于非常非常大的结构,无论如何您都会遇到 WhosebugError
s,但是对于可以直接或间接包含自身的对象,没有办法做到这一点使用类似这样的东西。
// 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;
}
我读过这个主题: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;
}
我会避免 clone
。 clone
被广泛认为已损坏(参见例如 Joshua Bloch 的 Effective Java,或搜索此站点)。相反,您可以编写自己的方法。
我写了一个我认为可行的方法 deepCopy
。它使用 IdentityHashMap
来发现先前遇到的 Cell
以避免多次计算其副本。
请注意,此方法仍然是递归的,因此对于非常非常大的结构,无论如何您都会遇到 WhosebugError
s,但是对于可以直接或间接包含自身的对象,没有办法做到这一点使用类似这样的东西。
// 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;
}