我想使用构造函数对对象数组进行深度复制。
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];
}
但是,由于某种原因,我上面的内容不起作用。我有我运行的自动化测试,但它没有通过这些测试。所以这里有一个错误,我不确定它是什么。
最佳答案
您实现的是一个浅副本。要实现深复制,您必须 改变
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();
注意事项:
- 以上假设复制构造函数、工厂方法和克隆方法分别实现了“正确”的复制,这取决于 Position 类;见下文。
clone
方法只有在Position
明确支持时才有效,这通常被认为是一种较差的解决方案。此外,您需要注意clone
的 native 实现(即Object.clone()
方法)执行浅拷贝1。
事实上在Java中实现深度复制的一般问题是复杂的。在 Position
类的情况下,人们会假设属性都是原始类型(例如整数或 double ),因此深度复制与浅层复制没有实际意义。但是如果有引用属性,那么你必须依赖复制构造函数/工厂方法/克隆方法来完成你需要的那种复制。在每种情况下都需要对其进行编程。在一般情况下(您必须处理循环)这很困难并且需要每个类实现特殊方法。
还有一种潜在方法可以复制对象数组。如果数组中的对象是可序列化,那么您可以通过使用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()
的 Object 实现执行浅拷贝,但这可能会被覆盖。 clone
的 javadoc 指定“契约(Contract)”如下:
"Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object x, the expression:
x.clone() != x
will be true, and that the expression:x.clone().getClass() == x.getClass()
will be true, but these are not absolute requirements. While it is typically the case that:x.clone().equals(x)
will be true, this is not an absolute requirement."
“契约(Contract)”中没有任何内容谈到深度复制与浅层复制。因此,如果您打算在此上下文中使用 clone
,则需要了解实际类 clone
方法的行为方式。
关于java - 对象数组的深拷贝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3947227/