Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deep copy of an object Java

Tags:

java

clone

I am trying to clone an object of MyGraph and I want it to be a deep copy so the arraylists inside the object are also cloned. Right now I have:

public static MyGraph deepCopy(MyGraph G){
    MyGraph Copy = (MyGraph) G.clone();

    Copy.VertexG = (ArrayList<Integer>) G.VertexG.clone();
    Copy.EdgeG = (ArrayList<String>) G.EdgeG.clone();

    return Copy;
}

This returns an error when it tries to clone the arraylist. I am not sure if this is the right way to add the arraylists to the object.

like image 610
Paul Avatar asked Oct 22 '22 16:10

Paul


1 Answers

The clone operation in ArrayList returns a shallow copy of the object, and will not be suitable for your purposes. The manual workaround is to:

  1. Create a target array list of the same size as the source list
  2. Iterate the source list and create a clone of each of it's items, into the target list

Obviously, this will only work if the array list contains items that implement clone, and in addition that the items clone operation actually returns a deep copy. In other words, its not guaranteed. Actually, implementing deep clone functionality for Java objects is not at all easy, refer to extensive discussions in Java: recommended solution for deep cloning/copying an instance and other SO threads to get a feel for the options available. In addition to the answers provided there, here are some other options:

Serialization

If all (the required) objects in your hierarchy can be serialized then you can use this simple code to do a deep clone:

public MyGraph deepCopy() {
    try {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream(256);
        final ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);
        oos.close();

        final ObjectInputStream ois = new ObjectInputStream(
                new ByteArrayInputStream(baos.toByteArray()));
        final MyGraph clone = (QuicksortTest) ois.readObject();
        return clone;
    } catch (final Exception e) {
        throw new RuntimeException("Cloning failed");
    }
}

Note that some deep-clone libraries combine standard Java serialization with reflection hacks and/or byte code instrumentation in order to make the entire object hierarchy fully serializable. You may, or may not, need that.

Copy tools

For example, Dozer, provide fast deep-copy functionality. Orika can also achieve the same, albeit with more configuration:

public MyGraph deepCopy() {
    final DozerBeanMapper mapper = new DozerBeanMapper();
    final QuicksortTest clone = mapper.map(this, MyGraph.class);
    return clone;
}

The only downside of course, being the additional dependencies you need to pull into your project.

On a total tangent, your deepCopy method should not be static. Also, you should seriously considering encapsulating the state of your object by making it private and implementing getters/setters.

like image 173
Perception Avatar answered Oct 30 '22 17:10

Perception