Cloning is the process of creating a copy of an Object. Java Object class comes with native clone()
method that returns the copy of the existing instance. Since Object is the base class in Java, all objects by default support cloning.
If you want to use Java Object clone() method, you have to implement the java.lang.Cloneable
marker interface. Otherwise, it will throw CloneNotSupportedException
at runtime. Also Object clone is a protected method, so you will have to override it. Let’s look at Object cloning in Java with an example program.
package com.journaldev.cloning;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class Employee implements Cloneable {
private int id;
private String name;
private Map<String, String> props;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, String> getProps() {
return props;
}
public void setProps(Map<String, String> p) {
this.props = p;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
We are using Object clone() method, so we have implemented the Cloneable
interface. We are calling the superclass clone() method i.e. Object clone() method.
Let’s create a test program to use the object clone() method to create a copy of the instance.
package com.journaldev.cloning;
import java.util.HashMap;
import java.util.Map;
public class CloningTest {
public static void main(String[] args) throws CloneNotSupportedException {
Employee emp = new Employee();
emp.setId(1);
emp.setName("Pankaj");
Map<String, String> props = new HashMap<>();
props.put("salary", "10000");
props.put("city", "Bangalore");
emp.setProps(props);
Employee clonedEmp = (Employee) emp.clone();
// Check whether the emp and clonedEmp attributes are same or different
System.out.println("emp and clonedEmp == test: " + (emp == clonedEmp));
System.out.println("emp and clonedEmp HashMap == test: " + (emp.getProps() == clonedEmp.getProps()));
// Let's see the effect of using default cloning
// change emp props
emp.getProps().put("title", "CEO");
emp.getProps().put("city", "New York");
System.out.println("clonedEmp props:" + clonedEmp.getProps());
// change emp name
emp.setName("new");
System.out.println("clonedEmp name:" + clonedEmp.getName());
}
}
Output:
emp and clonedEmp == test: false
emp and clonedEmp HashMap == test: true
clonedEmp props:{city=New York, salary=10000, title=CEO}
clonedEmp name:Pankaj
If our Employee class won’t implement Cloneable
interface, the above program will throw CloneNotSupportedException
runtime exception.
Exception in thread "main" java.lang.CloneNotSupportedException: com.journaldev.cloning.Employee
at java.lang.Object.clone(Native Method)
at com.journaldev.cloning.Employee.clone(Employee.java:41)
at com.journaldev.cloning.CloningTest.main(CloningTest.java:19)
Let’s look into the above output and understand what’s happening with Object clone()
method.
emp and clonedEmp == test: false
: It means that emp and clonedEmp are two different objects, not referring to the same object. This is in agreement with the java object cloning requirement.emp and clonedEmp HashMap == test: true
: So both emp and clonedEmp object variables refer to the same object. This can be a serious data integrity issue if we change the underlying object value. Any change in the value might get reflected to the cloned instance too.clonedEmp props:{city=New York, salary=10000, title=CEO}
: We didn’t make any change in clonedEmp properties, but still, they got changed because both emp and clonedEmp variables are referring to the same object.This is happening because the default Object clone() method creates a shallow copy. It can be a problem when you want to create totally detached objects through cloning process. This can lead to unwanted results, hence the need to properly override the Object clone() method.clonedEmp name:Pankaj
: What happened here?We changed the emp name but clonedEmp name didn’t change. It’s because String is immutable. So when we are setting emp name, a new string is created and emp name reference is changed in this.name = name;
.Hence clonedEmp name remains unchanged. You will find similar behavior for any primitive variable types too. So we are good with java object default cloning as long as we have only primitive and immutable variables in the object.There are two types of object cloning - shallow cloning, and deep cloning. Let’s understand each of them and find out the best way to implement cloning in our Java programs.
The default implementation of Java Object clone() method is using shallow copy. It’s using reflection API to create the copy of the instance. The below code snippet showcase the shallow cloning implementation.
@Override
public Object clone() throws CloneNotSupportedException {
Employee e = new Employee();
e.setId(this.id);
e.setName(this.name);
e.setProps(this.props);
return e;
}
In deep cloning, we have to copy fields one by one. If we have a field with nested objects such as List, Map, etc. then we have to write the code to copy them too one by one. That’s why it’s called deep cloning or deep copy. We can override the Employee clone method like the following code for deep cloning.
public Object clone() throws CloneNotSupportedException {
Object obj = super.clone(); //utilize clone Object method
Employee emp = (Employee) obj;
// deep cloning for immutable fields
emp.setProps(null);
Map<String, String> hm = new HashMap<>();
String key;
Iterator<String> it = this.props.keySet().iterator();
// Deep Copy of field by field
while (it.hasNext()) {
key = it.next();
hm.put(key, this.props.get(key));
}
emp.setProps(hm);
return emp;
}
With this clone() method implementation, our test program will produce the following output.
emp and clonedEmp == test: false
emp and clonedEmp HashMap == test: false
clonedEmp props:{city=Bangalore, salary=10000}
clonedEmp name:Pankaj
In most of the cases, this is what we want. The clone() method should return a new object totally detached from the original instance. So if you are thinking to use Object clone and cloning in your program, do it wisely and override it properly by taking care of mutable fields. It could be a daunting task if your class extends other class that in turn extends other class and so on. You will have to go all the way in the Object inheritance hierarchy to take care of the deep copy of all the mutable fields.
One way to easily perform deep cloning is through serialization. But serialization is an expensive procedure and your class should implement Serializable
interface. All the fields and superclasses must implement Serializable too.
If you are already using Apache Commons Util classes in your project and your class is serializable, then use the below method.
Employee clonedEmp = org.apache.commons.lang3.SerializationUtils.clone(emp);
We can define a copy constructor to create a copy of the object. Why to depend on the Object clone() method at all? For example, we can have an Employee copy constructor like the following code.
public Employee(Employee emp) {
this.setId(emp.getId());
this.setName(emp.getName());
Map<String, String> hm = new HashMap<>();
String key;
Iterator<String> it = emp.getProps().keySet().iterator();
// Deep Copy of field by field
while (it.hasNext()) {
key = it.next();
hm.put(key, emp.getProps().get(key));
}
this.setProps(hm);
}
Whenever we need a copy of employee object, we can get it using Employee clonedEmp = new Employee(emp);
. However writing copy constructor can be a tedious job if your class has a lot of variables, especially primitive and immutable.
Use default Object clone() method only when your class has primitives and immutable variables or you want shallow copy. In case of inheritance, you will have to check all the classes you are extending till the Object level.
You can also define copy constructor if your class has mostly mutable properties.
Utilize Object clone() method by calling super.clone()
in overridden clone method, then make necessary changes for deep copying of mutable fields.
If your class is serializable, you can use serialization for cloning. However, it will come with a performance hit, so do some benchmarking before using serialization for cloning.
If you are extending a class and it has defined clone method properly using deep copy, then you can utilize default clone method. For example, we have properly defined clone() method in Employee class as follows.
@Override
public Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
Employee emp = (Employee) obj;
// deep cloning for immutable fields
emp.setProps(null);
Map<String, String> hm = new HashMap<>();
String key;
Iterator<String> it = this.props.keySet().iterator();
// Deep Copy of field by field
while (it.hasNext()) {
key = it.next();
hm.put(key, this.props.get(key));
}
emp.setProps(hm);
return emp;
}
We can create a child class and utilize the superclass deep cloning as follows.
package com.journaldev.cloning;
public class EmployeeWrap extends Employee implements Cloneable {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String t) {
this.title = t;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
The EmployeeWrap
class doesn’t have any mutable properties and it’s utilizing superclass clone() method implementation. If there are mutable fields, then you will have to take care of deep copying of only those fields. Here is a simple program to test if this way of cloning works fine or not.
package com.journaldev.cloning;
import java.util.HashMap;
import java.util.Map;
public class CloningTest {
public static void main(String[] args) throws CloneNotSupportedException {
EmployeeWrap empWrap = new EmployeeWrap();
empWrap.setId(1);
empWrap.setName("Pankaj");
empWrap.setTitle("CEO");
Map<String, String> props = new HashMap<>();
props.put("salary", "10000");
props.put("city", "Bangalore");
empWrap.setProps(props);
EmployeeWrap clonedEmpWrap = (EmployeeWrap) empWrap.clone();
empWrap.getProps().put("1", "1");
System.out.println("empWrap mutable property value = "+empWrap.getProps());
System.out.println("clonedEmpWrap mutable property value = "+clonedEmpWrap.getProps());
}
}
Output:
empWrap mutable property value = {1=1, city=Bangalore, salary=10000}
clonedEmpWrap mutable property value = {city=Bangalore, salary=10000}
So it worked perfectly as we expected.
That’s all about Object cloning in java. I hope you got some idea about Java Object clone() method and how to properly override it without any adverse effect.
You can download the project from my GitHub Repository.
Reference: API Doc for Object clone
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
Object cloning in Java is the easiest way to get a new object with a state. You don’t need to go through the whole process of calling new operator to create an object and assign value to its fields.
- knpcode
In case of HashMap where we have immutable Key and immutable value. We do not need to do deep cloning explicitly. HashMap override Object clone() method, which will take care of providing functionality of deep cloning.
- Prakash
thanks
- Arun SIngh
thanks alot
- Anil Gupta From Sidhi Mp
please note that are deep clone frameworks such as beanlib (which can even clone instrumented hibernate classes) so that you won’t have to write boiler plate code.
- Elhanan Maayan
Great, I got it. Thanks for your post :)
- Tran Nam
Hi Pankaj, when i run this class as it is in eclipse using open-jdk-6, it gives me second output and i did not understand one thing,after cloning setting new values on actual object obviously differ from the cloned object right ?
- suhasini