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.
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 thePositionclass. 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:
cloneapproach will only work ifPositionexplicitly 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
Positionclass, 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
ObjectOutputStreamandObjectInputStreamserialize and then deserialize the array. However:transientfields 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
Positionclasses 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 forclonespecifies the "contract" as follows:Nothing in the "contract" talks about deep versus shallow copying. So if you are going to use
clonein this context, you need to know how the actual classesclonemethod behaves.