Java Object clone() Method – Cloning in Java

Filed Under: Java

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.

Java Object Cloning

java clone object

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.

Using 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

CloneNotSupportedException at Runtime

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)

Java CloneNotSupportedException

Understanding Object Cloning

Let’s look into the above output and understand what’s happening with Object clone() method.

  1. 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.
  2. 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.
  3. 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.
  4. 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.

Object Cloning Types

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.

1. Shallow Cloning

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;
}

2. Deep Cloning

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.

Cloning using Serialization?

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.

Using Apache Commons Util

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);

Copy Constructor for Cloning

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.

Java Object Cloning Best Practices

  1. 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.
  2. You can also define copy constructor if your class has mostly mutable properties.
  3. Utilize Object clone() method by calling super.clone() in overridden clone method, then make necessary changes for deep copying of mutable fields.
  4. 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.
  5. 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

Comments

  1. knpcode says:

    Object cloning in Java is the easiest way to get a new object with a state. You don鈥檛 need to go through the whole process of calling new operator to create an object and assign value to its fields.

  2. Prakash says:

    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.

    1. Shabd says:

      HI Pankaj,

      Thanks for wonderful article.You been of great help always.
      Coming to question if HashMap key/value is immutable then why we are doing deep cloning here?

      1. Pankaj says:

        HashMap keys should be immutable for its proper functioning. It’s not a requirement.

  3. Anil Gupta From Sidhi Mp says:

    thanks alot

  4. Elhanan Maayan says:

    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.

  5. Tran Nam says:

    Great, I got it. Thanks for your post 馃檪

  6. suhasini says:

    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 ?

    1. Pankaj says:

      First of all thanks for executing the program. I forgot to comment the clone() method while publishing. I have commented it now.
      Second thing is that when we use default cloning, it just copies the reference of the object that is clear from boolean output of ct1.getProps() == ct2.getProps(). So to avoid any changes getting reflected from one object to other its necessary to provide our own implementation of clone method.

Leave a Reply

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

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages