您实现的是一个浅层副本。要实现深度拷贝,必须进行更改
data[i] = other.data[i];
到将 的副本分配给 的某个事物。如何执行此操作取决于类。可能的替代方案是:other.data[i]
data[i]
Position
-
复制构造函数:
data[i] = new Position(other.data[i]);
-
工厂方法:
data[i] = createPosition(other.data[i]);
-
克隆:
data[i] = (Position) other.data[i].clone();
笔记:
- 以上假设复制构造函数、工厂方法和克隆方法分别实现“right”类型的复制,具体取决于 Position 类;见下文。
- 该方法只有在明确支持的情况下才有效,这通常被认为是一种较差的解决方案。此外,您需要注意(即方法)的本机实现会执行浅层复制1。
clone
Position
clone
Object.clone()
事实上,在Java中实现深度复制的一般问题很复杂。在类的情况下,人们会假设属性都是基元类型(例如int或doubles),因此深度复制与浅复制是没有意义的。但是,如果有引用属性,那么您必须依靠复制构造函数/工厂方法/克隆方法来执行所需的复制类型。在每种情况下,都需要对其进行编程。在一般情况下(您必须处理周期),这很困难,并且需要每个类实现特殊方法。Position
还有另一种可能的方法可以复制对象数组。如果数组中的对象是可序列化的,则可以通过使用复制它们,序列化和反序列化数组。然而:ObjectOutputStream
ObjectInputStream
- 这很贵,
- 仅当对象(可传递地)可序列化时才起作用,并且
- 不会复制任何字段的值。
transient
不建议通过序列化进行复制。最好支持克隆或其他方法。
总而言之,在Java中最好避免深度复制。
最后,为了回答你关于类复制构造函数工作的问题,我希望它是这样的:Position
public class Position {
private int x;
private int y;
...
public Position(Position other) {
this.x = other.x;
this.y = other.y;
}
...
}
正如@Turtle所说,没有魔法。您可以实现一个构造函数(手动),该构造函数通过从现有实例复制来初始化其状态。
1 - 指定 clone()
的对象实现执行浅层复制,但可能会被覆盖。用于克隆
的 javadoc 指定“合约”,如下所示:
“创建并返回此对象的副本。“复制”的确切含义可能取决于对象的类。一般的意图是,对于任何对象 x,表达式:x.clone() != x
将是 true,并且表达式: x.clone().getClass() == x.getClass()
将为 true,但这些不是绝对要求。虽然通常情况是:x.clone().equals(x)
将为真,但这不是绝对的要求。
“合同”中没有任何内容涉及深度复制与浅层复制。因此,如果要在此上下文中使用 clone
,则需要知道实际的类 clone
方法的行为方式。