Java : Shallow and Deep Object Cloning

Pr-requisite : Marker Interface in Java and Use, CloneNotSupportedException

In object oriented programming object copy or copy of object are possible many ways like copy constructor or copy of object. Here we will focus on both the ways for copy of object.

  • Shallow Copy or Shallow Cloning
  • Deep Copy or Deep Cloning

See also : Java : Shallow Cloning Vs Deep Cloning

Example of Shallow Cloning and Deep Cloning
Java : Shallow Cloning and Deep Cloning

Shallow Copy or Shallow Cloning

Whenever we use default implementation of copy of object means it create new instance of object and copies all the fields to the object new fields and if fields are non primitive or reference type variable to copy to new fields as reference of that non-primitive fields.

clone() method by default support shallow copy of object().  for implementing clone() method you have to implement Cloneable interface which is marker interface.

Shallow copy example by constructor

import java.util.Arrays;

public class Courses {
String[] courseArr;
// Shallow copy by constructor because in copy taking reference of object
public Courses(String[] courseArr) {
super();
this.courseArr = courseArr;
}
@Override
public String toString() {
return "Courses [courseArr=" + Arrays.toString(courseArr) + "]";
}

public static void main(String[] str) {
String[] courseArr = { "Math", "Physics", "Chemistry", "Hindi", "English" };
Courses courses = new Courses(courseArr);
System.out.println(courses);
courseArr[2] = "Computer";//while changing in passed object will reflect on copy of object
System.out.println(courses);
}
}

Output


Courses [courseArr=[Math, Physics, Chemistry, Hindi, English]]
Courses [courseArr=[Math, Physics, Computer, Hindi, English]]

Shallow copy by clone method

In this example doing  shallow copy by clone method default way by implementing Cloneable interface and overriding clone() method which will by default make copy of object but here sub object course field in Student object will take reference of copied student object. It means if make any change on course object values will reflect same on copy object. clone method will always throw CloneNotSupportedException which always need to handle.

class Courses {
String course1;
String course2;
String course3;

public Courses(String course1, String course2, String course3) {
this.course1 = course1;
this.course2 = course2;
this.course3 = course3;
}
}

class Student implements Cloneable {
int id;
String name;
Courses courses;

public Student(int id, String name, Courses courses) {
this.id = id;
this.name = name;
this.courses = courses;
}

// Default version of clone() method. It creates shallow copy of an object.
// CloneNotSuportedException is checked exception always need to handle that
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

public class ShallowCopyInJava {
public static void main(String[] args) {
Courses science = new Courses("Physics", "Chemistry", "Math");
Student student1 = new Student(1020, "Saurabh", science);
Student student2 = null;

try {
// Creating a clone of student1 and assigning it to student2
student2 = (Student) student1.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}

// Printing the subject3 of 'student1'
System.out.println(student1.courses.course3); // Output : Maths

// Changing the course3 of 'student2'
student2.courses.course3 = "Biology";

// This change will be reflected in original student 'student1'
System.out.println(student1.courses.course3); // Output : Biology
}
}

Output


Math
Biology

Note: If class is having only primitive type values or Immutable object there is no difference between Shallow and Deep Cloning of object.

Deep Copy or Deep Cloning

Whenever we need own copy not to use default implementation (shallow copy or shallow cloning) of object. Always implement according to our need and make sure all the member of  class also having deep copied of fields.

If using cloneable interface and overriding clone() method of object class make sure member objects /reference objects also having deep copy of fields.

Deep copy example by constructor

import java.util.Arrays;

public class Courses {
String[] courseArr;

// Deep copy object because copy actual fields value not references
public Courses(String[] courseArr) {
super();
if (courseArr != null) {
this.courseArr = new String[courseArr.length];
for (int i = 0; i <courseArr.length; i++) {
this.courseArr[i] = courseArr[i];
}
}
}

@Override
public String toString() {
return "Courses [courseArr=" + Arrays.toString(courseArr) + "]";
}

public static void main(String[] str) {
String[] courseArr = { "Math", "Physics", "Chemistry", "Hindi", "English" };
Courses courses = new Courses(courseArr);
System.out.println(courses);
courseArr[2] = "Computer";// while changing in passed object will reflect on copy of object
System.out.println(courses);
}
}

Output


Courses [courseArr=[Math, Physics, Chemistry, Hindi, English]]
Courses [courseArr=[Math, Physics, Chemistry, Hindi, English]]

Deep copy by clone method
In this example doing  deep copy by clone method but handle copying each individual reference object copy separately as in Student class clone() method. It means if make any change on course object values will not reflect same on copy object. clone method will always throw CloneNotSupportedException which always need to handle.

class Courses implements Cloneable{
String course1;
String course2;
String course3;

public Courses(String course1, String course2, String course3) {
this.course1 = course1;
this.course2 = course2;
this.course3 = course3;
}

protected Object clone() throws CloneNotSupportedException
{
return super.clone();
}
}

class Student implements Cloneable
{
int id;
String name;
Courses courses;

public Student(int id, String name, Courses courses)
{
this.id = id;
this.name = name;
this.courses = courses;
}

//Overriding clone() method to create a deep copy of an object.
//CloneNotSuportedException is checked exception always need to handle that

protected Object clone() throws CloneNotSupportedException
{
Student student = (Student) super.clone();
student.courses = (Courses) courses.clone();
return student;
}
}

public class DeepCopyInJava
{
public static void main(String[] args)
{
Courses science = new Courses("Physics", "Chemistry", "Math");
Student student1 = new Student(1020, "Saurabh", science);
Student student2 = null;

try
{
//Creating a clone of student1 and assigning it to student2
student2 = (Student) student1.clone();
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}

//Printing the subject3 of 'student1'
System.out.println(student1.courses.course3); //Output : Math
//Changing the subject3 of 'student2'
student2.courses.course3 = "Biology";
//This change will not be reflected in original student 'student1'
System.out.println(student1.courses.course3); //Output : Math
}
}

Output


Math
Math

Conclusion

Here you learn about Shallow and Deep copy  of object by constructor and implementing by clone() method of Cloneable Interface which is marker interface.