对象数组的深度副本
我想用一个构造函数来创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();
笔记:
- 以上假设复制构造函数,工厂方法和克隆方法分别根据Position类实现“正确”的复制types; 见下文。
-
clone
方法只有在Position
明确地支持它的时候才会起作用,这通常被认为是一个劣质的解决scheme。 此外,你需要知道clone
的本地实现(即Object.clone()
方法)做一个浅拷贝。
事实上,在Java中执行深度复制的一般问题是复杂的。 在Position
类的情况下,我们可以假定这些属性都是原始types(例如整数或双精度),因此深度和浅度复制是没有意义的。 但是,如果有引用属性,那么您必须依赖复制构造函数/工厂方法/克隆方法来进行所需的复制。 在每种情况下都需要编程。在一般情况下(你必须处理周期)很难,并且要求每个类都实现特殊的方法。
还有另一种可能的方法来复制对象数组。 如果数组中的对象是可序列化的 ,那么可以使用ObjectOutputStream
和ObjectInputStream
序列化,然后反序列化数组。 然而:
- 这很贵,
- 它只适用于对象是(可传递)序列化的
- 任何
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();