Cloning is a process of creating an exact copy of an existing object in the memory.
In java, clone() method of java.lang.Object class is used for cloning process. This method creates an exact copy of an object on which it is called through field-by-field assignment and returns the reference of that object.
Not all the objects in java are eligible for cloning process. The objects which implement Cloneable interface are only eligible for cloning process.
Cloneable interface is a marker interface which is used to provide the marker to cloning process.
Both shallow copy and deep copy are related to this cloning process. The default version of clone() method creates the shallow copy of an object. To create the deep copy of an object, you have to override the clone() method. Let’s see how these shallow copy and deep copy work.
The default version of clone() method creates the shallow copy of an object. The shallow copy of an object will have exact copy of all the fields of original object. If original object has any references to other objects as fields, then only references of those objects are copied into clone object, copy of those objects are not created. That means any changes made to those objects through clone object will be reflected in original object or vice-versa. Shallow copy is not 100% disjoint from original object. Shallow copy is not 100% independent of original object.
Below is the example which creates the shallow copy of an object ‘jbkemployee1’.
JbkJob.java
package com.javabykiran.shallowcopy;
public class JbkJob {
String task1;
String task2;
String task3;
public JbkJob(String task1, String task2, String task3) {
this.task1 = task1;
this.task2 = task2;
this.task3 = task3;
}
}
JbkEmployee.java
package com.javabykiran.shallowcopy;
public class JbkEmployee implements Cloneable {
int id;
String name;
JbkJob job;
public JbkEmployee(int id, String name, JbkJob job) {
this.id = id;
this.name = name;
this.job = job;
}
// Default version of clone() method. It creates shallow copy of an object.
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
JbkShallowCopy.java
package com.javabykiran.shallowcopy;
public class JbkShallowCopy {
public static void main(String[] args) {
JbkJob dataentry = new JbkJob("Type", "Print", "Scan");
JbkEmployee jbkemployee1 = new JbkEmployee(01, "John", dataentry);
JbkEmployee jbkemployee2 = null;
try {
// Creating a clone of employee1 and assigning it employee2
jbkemployee2 = (JbkEmployee) jbkemployee1.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
// Printing the task3 of employee1
System.out.println("Task3 of jbkemployee1 is = " + jbkemployee1.job.task3); // Output:-Scan
// Change the task3 of employee2
jbkemployee2.job.task3 = "PhotoCopy";
// this change will be reflected in original employee 'employee1'
// Printing the task3 of employee1
System.out.println("Task3 of jbkemployee1 is = " + jbkemployee1.job.task3); // Output:-Photocopy
}
}
In the above example, ‘jbkemployee1‘ is an object of ‘JbkEmployee‘ class which has three fields – id, name and job. ‘Job‘ is a reference variable pointing to a ‘JbkJob‘ type object. Clone of ‘jbkemployee1 ‘ is created by calling clone method on it and assigned it to ‘jbkemployee2‘. As default version of clone method creates the shallow copy, the ‘course‘ field of both ‘jbkemployee1 ‘ and ‘jbkemployee2‘ will be pointing to same ‘JbkJob‘ object. So, any changes made to this object through ‘jbkemployee2‘ will be reflected in ‘student1‘ or vice-versa.
Deep copy of an object will have exact copy of all the fields of original object just like shallow copy. But in additional, if original object has any references to other objects as fields, then copy of those objects are also created by calling clone() method on them. That means clone object and original object will be 100% disjoint. They will be 100% independent of each other. Any changes made to clone object will not be reflected in original object or vice-versa.
To create a deep copy of an object, you have to override the clone() method as demonstrated in the below example.
JbkJob.java
package com.javabykiran.deepcopy;
public class JbkJob implements Cloneable {
String task1;
String task2;
String task3;
public JbkJob(String task1, String task2, String task3) {
this.task1 = task1;
this.task2 = task2;
this.task3 = task3;
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
JbkEmployee.java
package com.javabykiran.deepcopy;
public class JbkEmployee implements Cloneable {
int id;
String name;
JbkJob job;
public JbkEmployee(int id, String name, JbkJob job) {
this.id = id;
this.name = name;
this.job = job;
}
// overriding clone() method to create a deep copy of an object.
protected Object clone() throws CloneNotSupportedException {
JbkEmployee employee = (JbkEmployee) super.clone();
employee.job = (JbkJob) job.clone();
return employee;
}
}
JbkDeepCopy.java
package com.javabykiran.deepcopy;
public class JbkDeepCopy {
public static void main(String[] args) {
JbkJob dataentry = new JbkJob("Type", "Print", "Scan");
JbkEmployee jbkemployee1 = new JbkEmployee(01, "John", dataentry);
JbkEmployee jbkemployee2 = null;
try {
// Creating a clone of employee1 and assigning it employee2
jbkemployee2 = (JbkEmployee) jbkemployee1.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
// Printing the task3 of employee1
System.out.println("Task3 of jbkemployee1 is = " + jbkemployee1.job.task3); // Output:-Scan
// Change the task3 of employee2
jbkemployee2.job.task3 = "PhotoCopy";
// This change will not be reflected in original employee 'employee1'
// Printing the task3 of employee1
System.out.println("Task3 of jbkemployee1 is = " + jbkemployee1.job.task3); // Output:-Scan
}
}