[英]Deep copy of an object array
我想使用构造函数制作对象数组的深层副本。
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();
笔记:
clone
方法只有在Position
明确支持它时才有效,这通常被认为是一种劣质的解决方案。 此外,您需要注意clone
的本机实现(即Object.clone()
方法)执行浅拷贝1 。 事实上,在 Java 中实现深度复制的一般问题是复杂的。 在Position
类的情况下,人们会假设属性都是原始类型(例如 ints 或 doubles),因此深拷贝与浅拷贝没有实际意义。 但是如果有引用属性,那么你必须依靠复制构造函数/工厂方法/克隆方法来做你需要的那种复制。 在每种情况下都需要对其进行编程。在一般情况下(您必须处理循环),这很困难并且需要每个类实现特殊方法。
还有另一种可能的方法来复制对象数组。 如果数组中的对象是可序列化的,那么您可以通过使用ObjectOutputStream
和ObjectInputStream
serialize 来复制它们,然后反序列化数组。 然而:
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 指定“合同”如下:
"创建并返回此对象的副本。"复制"的确切含义可能取决于对象的类。一般的意图是,对于任何对象 x,表达式:
x.clone() != x
将是true,并且表达式:x.clone().getClass() == x.getClass()
将是 true,但这不是绝对要求。虽然通常情况下是:x.clone().equals(x)
为真,这不是绝对要求。”
“合同”中没有任何内容涉及深复制与浅复制。 因此,如果您打算在此上下文中使用clone
,您需要知道实际的类clone
方法的行为方式。
当你说:
data[i]=other.data[i];
您只是在复制引用列表(假设这是一个对象数组)。 如果要进行深拷贝,则需要使用new
为数组中的每个对象创建一个新实例。
而不是说:
data[i]=other.data[i]
您需要为Position
创建一个复制构造函数(换句话说,Position 的构造函数接受另一个Position
并复制其中的原始数据)并说data[i]=new Position(other.data[i]);
基本上你的“深拷贝”构造函数PositionList
是一个拷贝构造函数,虽然拷贝构造函数确实倾向于表示一个深拷贝,所以deepCopy
参数是不必要的。
这是我使用的一个函数:
function copy(arr) {
return arr
.map(x => Object
.keys(x)
.reduce((acc, y) => {
acc[y] = x[y]
return acc
}, {}))
}
它仅适用于具有单个级别的对象的数组。
这应该是一个“深”副本
int [] numbers = { 2, 3, 4, 5};
int [] numbersClone = (int[])numbers.clone();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.