What is a Deep Copy in Java?

When we make a deep copy of an object in Java, that means it will be copied along with the objects to which it refers.

Let’s say we have an object (obj1) that contains references to the other two objects. By its deep cloning, we will get a new object (obj2) whose references will point to two completely new objects of the same type.

 
Deep Copy in Java


We can perform a deep copy using the clone() method from the Object class and implement the Cloneable interface, similar to what we did in shallow object cloning.

Example of Deep Copy in Java

Let’s create two classes (ClassA and ClassC) that implement the Cloneable interface and override the clone() method. ClassA will have a reference to ClassC.

class ClassA implements Cloneable {

  private int someNum;
  private ClassC nestedObjectReference;

  @Override
  public Object clone() throws CloneNotSupportedException {
    ClassA classA = (ClassA) super.clone();

    // with this, we are ensuring that deep copy will be performed
    classA.setNestedObjectReference((ClassC) this.nestedObjectReference.clone());

    return classA;
  }

  // constructor, getters and setters

}

class ClassC implements Cloneable {

  private String classData;

  public ClassC() {

  }

  @Override
  public Object clone() throws CloneNotSupportedException {
    return super.clone();
  }

 // constructor, getters and setters

}

Here, both classes implement the Cloneable interface and override the clone() method from the Object class. Just in ClassA, we added more logic to ensure that deep copy will be performed.

Now let’s test this:

public class Test {

  public static void main(String[] args) throws CloneNotSupportedException {

    ClassA obj1 = new ClassA();

    obj1.setSomeNum(5);
    obj1.setNestedObjectReference(new ClassC("one"));

    ClassA obj2 = (ClassA) obj1.clone();

    System.out.println("Object 1 ...");
    System.out.println(obj1.getSomeNum());
    System.out.println(obj1.getNestedObjectReference().getClassData());

    System.out.println("Object 2 ...");
    System.out.println(obj2.getSomeNum());
    System.out.println(obj2.getNestedObjectReference().getClassData());

    // now change the value of the nestedObjectReference using obj2
    obj2.getNestedObjectReference().setClassData("two");

    System.out.println();
    System.out.println(obj1.getNestedObjectReference().getClassData());
    System.out.println(obj2.getNestedObjectReference().getClassData());

  }

}
Output: Object 1 … 5 one Object 2 … 5 one one two
 
Here, we first verified that we got two objects with the same fields, and then we used the obj2 to change the value of the nested object.  The value got changed only for the obj2 since the obj1 has a reference to a completely separate object of type ClassC.
 
And that is a deep copy of objects in Java!

Advantages of Deep Copy

  • The nested objects will be copied too. After the cloning, both objects will have references to different objects, and with that, if we modify a field in one object, that will not be reflected in the other.
  • There are some additional libraries that we can use to perform a deep copy, so we don’t need to use the clone() method.

Note: Performing a deep copy can be tricky to implement when working with complex objects, and memory consumption can also be an issue.

That’s it!

Leave a Reply

Your email address will not be published. Required fields are marked *