对象数组的深拷贝
我想使用构造函数制作对象数组的深层副本。
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];
}
但是,由于某种原因,我上面的内容不起作用。我运行了自动化测试,但这些测试失败了。所以这里有一个错误,我不确定它是什么。
I want to make a deep copy of an object array using a constructor.
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];
}
However, what I have above for some reason is not working. I have automated tests that I run, and its failing those tests. So theres an error an here that Im not sure what it is.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您所实现的是浅复制。要实现深层复制,您必须
更改
为将
other.data[i]
的副本分配给data[i]
的内容。如何执行此操作取决于Position
类。可能的替代方案是:复制构造函数:
data[i] = new Position(other.data[i]);
工厂方法:
data[i] = createPosition(other.data[i]);
克隆:
data[i] = (位置) other.data[i].clone();
注意:
clone
方法只有在Position
明确支持的情况下才有效,这通常被认为是一个较差的解决方案。此外,您需要注意clone
的本机实现(即Object.clone()
方法)会执行浅复制1。事实上,在Java中实现深复制的一般问题很复杂。对于
Position
类,我们会假设属性都是原始类型(例如整型或双精度型),因此深复制与浅复制是没有意义的。但是如果存在引用属性,那么您必须依赖复制构造函数/工厂方法/克隆方法来执行您需要的那种复制。在每种情况下都需要对其进行编程。并且在一般情况下(必须处理循环)这很困难并且需要每个类实现特殊的方法。还有另一种复制对象数组的潜在方法。如果数组中的对象是可序列化的,那么您可以通过使用
ObjectOutputStream
和ObjectInputStream
序列化和反序列化数组来复制它们。然而:transient
字段的值都不会被复制。不建议通过序列化进行复制。最好支持克隆或其他方法。
总而言之,在 Java 中最好避免深度复制。
最后,为了回答您关于
Position
类复制构造函数工作的问题,我希望它是这样的:正如 @Turtle 所说,没有涉及任何魔法。您(手动)实现一个构造函数,该构造函数通过从现有实例复制来初始化其状态。
1 - 指定
clone()
的对象实现执行浅复制,但这可能会被覆盖。clone
的 javadoc 指定“契约”如下:< super>“合同”中没有任何内容谈论深度复制与浅度复制。因此,如果您要在这种情况下使用
clone
,您需要了解实际的类clone
方法的行为方式。What you have implemented is a shallow copy. To implement a deep copy, you must
change
to some thing that assigns a copy of
other.data[i]
todata[i]
. How you do this depends on thePosition
class. Possible alternatives are:a copy constructor:
data[i] = new Position(other.data[i]);
a factory method:
data[i] = createPosition(other.data[i]);
clone:
data[i] = (Position) other.data[i].clone();
Notes:
clone
approach will only work ifPosition
explicitly supports it, and this is generally regarded as an inferior solution. Besides, you need to be aware that the native implementation ofclone
(i.e. theObject.clone()
method) does a shallow copy1.In fact the general problem of implementing deep copying in Java is complicated. In the case of the
Position
class, one would assume that the attributes are all primitive types (e.g. ints or doubles), and therefore a deep versus shallow copying is moot. But if there are reference attributes, then you have to rely on the copy constructor / factory method / clone method to do the kind of copying that you require. In each case it needs to be programmed in. And in the general case (where you have to deal with cycles) it is difficult and requires each class to implement special methods.There is one other potential way to copy an array of objects. If the objects in the array are serializable, then you can copy them by using
ObjectOutputStream
andObjectInputStream
serialize and then deserialize the array. However:transient
fields won't be copied.Copying by serialization is not recommended. It would be better to support cloning or some other method.
All in all, deep copying is best avoided in Java.
Finally, to answer your question about the
Position
classes copy constructor works, I expect it is something like this:As @Turtle says, there's no magic involved. You implement a constructor (by hand) that initializes its state by copying from an existing instance.
1 - It is specified that the Object implementation of
clone()
does a shallow copy, but this may be overridden. The javadoc forclone
specifies the "contract" as follows:Nothing in the "contract" talks about deep versus shallow copying. So if you are going to use
clone
in this context, you need to know how the actual classesclone
method behaves.当您说:
您只是复制引用列表(假设这是一个对象数组)。如果要进行深复制,则需要使用
new
为数组中的每个对象创建一个新实例。When you say:
You are just copying a list of references (assuming this is an array of objects). If you want to make a deep copy, you need to use
new
to create a new instance of each object in the array.而不是说:
您需要为
Position
创建一个复制构造函数(换句话说,一个 Position 的构造函数,它接受另一个Position
并复制其中的原始数据)并说data[i]=new Position(other.data[i]);
基本上你的“深层复制”构造函数
PositionList
是一个复制构造函数,尽管复制构造函数确实倾向于表示深层复制,因此不需要deepCopy
参数。Instead of saying:
You will want to make a copy constructor for
Position
(in other words, a constructor for Position that takes in anotherPosition
and copies the primitive data inside it) and saydata[i]=new Position(other.data[i]);
Basically your "deep copy" constructor the
PositionList
is a copy constructor, although copy constructor does tend to indicate a deep copy, so thedeepCopy
parameter is unnecessary.这是我使用的一个函数:
它仅适用于具有单个级别的对象的数组。
Here is a function I use:
It only works on arrays with objects with a single level.
这应该制作一个“深层”副本
This should make a "deep" copy