对象数组的深度副本

我想用一个构造函数来创build一个对象数组的深层拷贝。

public class PositionList { private Position[] data = new Position[0]; public PositionList(PositionList other, boolean deepCopy) { if (deepCopy){ size=other.getSize(); data=new Position[other.data.length]; for (int i=0;i<data.length;i++){ data[i]=other.data[i]; } 

不过,由于某种原因,我上面有什么不起作用。 我有我运行的自动化testing,并没有通过这些testing。 所以这里有一个错误,我不知道它是什么。

你已经实现的是一个拷贝。 要实现深层复制,您必须更改

 data[i] = other.data[i]; 

以某种方式将other.data[i]副本分配给data[i] 。 你如何做到这一点取决于Position类。 可能的select是:

  • 一个拷贝构造函数:

    data[i] = new Position(other.data[i]);

  • 工厂方法:

    data[i] = createPosition(other.data[i]);

  • 克隆:

    data[i] = (Position) other.data[i].clone();

笔记:

  1. 以上假设复制构造函数,工厂方法和克隆方法分别根据Position类实现“正确”的复制types; 见下文。
  2. clone方法只有在Position明确地支持它的时候才会起作用,这通常被认为是一个劣质的解决scheme。 此外,你需要知道clone的本地实现(即Object.clone()方法)做一个浅拷贝。

事实上,在Java中执行深度复制的一般问题是复杂的。 在Position类的情况下,我们可以假定这些属性都是原始types(例如整数或双精度),因此深度和浅度复制是没有意义的。 但是,如果有引用属性,那么您必须依赖复制构造函数/工厂方法/克隆方法来进行所需的复制。 在每种情况下都需要编程。在一般情况下(你必须处理周期)很难,并且要求每个类都实现特殊的方法。

还有另一种可能的方法来复制对象数组。 如果数组中的对象是可序列化的 ,那么可以使用ObjectOutputStreamObjectInputStream序列化,然后反序列化数组。 然而:

  • 这很贵,
  • 它只适用于对象是(可传递)序列化的
  • 任何transient字段的值都不会被复制。

不build议通过序列化进行复制。 支持克隆或其他方法会更好。

总而言之,在Java中最好避免深度复制。

最后,要回答你有关Position类复制构造函数的问题,我期望它是这样的:

 public class Position { private int x; private int y; ... public Position(Position other) { this.x = other.x; this.y = other.y; } ... } 

正如@Turtle所说,没有魔法可言。 你实现一个构造函数(手工),通过从现有的实例复制来初始化它的状态。

当你说:

 data[i]=other.data[i]; 

你只是复制一个引用列表(假设这是一个对象数组)。 如果要进行深层复制,则需要使用new来创buildarrays中每个对象的新实例。

而不是说:

 data[i]=other.data[i] 

你需要为Position创build一个拷贝构造函数(换言之,Position的构造函数在另一个Position并且拷贝其中的原始数据)并且声明data[i]=new Position(other.data[i]);

基本上你的“深拷贝”的构造函数PositionList是一个拷贝构造函数,虽然拷贝构造函数往往表示深拷贝,所以deepCopy参数是不必要的。

这应该是一个“深”的副本

 int [] numbers = { 2, 3, 4, 5}; int [] numbersClone = (int[])numbers.clone();