【问题标题】:Cloning in Java object that got in attribute the same object在属性相同的对象中克隆 Java 对象
【发布时间】:2015-11-03 18:26:57
【问题描述】:

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

我已经做了一些测试,它可以工作。现在,我的问题是克隆一个对象 A,该对象 A 获得了其他对象 A 的列表。例如:

        public class Cell {
            Cell[] listOfCells;
        }

我在 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();
        }

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

编辑:@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

【问题讨论】:

  • 发布错误堆栈可能会有所帮助;
  • 是这个吗?线程“主”java.lang.StackOverflowError 中的异常?
  • 如果你尝试做一个深拷贝,如果listOfCells可以包含this(无论是直接的还是间接的)你会遇到很大的问题。这并非不可能,但我不确定这是否值得。请问您能说明您要达到的目标吗?
  • @PaulBoddington 我已经编辑了我的第一篇文章。

标签: java cloning


【解决方案1】:

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

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

请注意,这个方法仍然是递归的,所以无论如何你都会遇到StackOverflowErrors 用于非常非常大的结构,但是对于可以直接或间接包含自身的对象,如果不使用类似的东西就没有办法做到这一点.

// 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;
}

【讨论】:

  • 谢谢,我会看这个,了解后回复。
  • @Eamnea 我已经编辑了我的答案。以前没有意义,因为我使用了一个不在您的问题中的构造函数。
  • 我做了一些测试,似乎符合我的要求。再次感谢。
【解决方案2】:

在您的 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;
}

【讨论】:

  • 是的,这就是我的本意。该代码只是一个示例。
  • 对不起,它还没有准备好,我的浏览器欺骗了我。现在应该可以使用了
  • 感谢您的帮助,'感谢它,但仍然发生溢出。
猜你喜欢
  • 2016-08-05
  • 2015-02-08
  • 1970-01-01
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多