Tutorial

Java Object clone() Method - Cloning in Java

Published on August 3, 2022
author

Pankaj

Java Object clone() Method - Cloning in 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

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Pankaj

author

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.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
March 21, 2019

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

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    February 27, 2018

    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

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      December 21, 2017

      thanks

      - Arun SIngh

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        February 26, 2016

        thanks alot

        - Anil Gupta From Sidhi Mp

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          March 24, 2011

          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

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            March 24, 2011

            Great, I got it. Thanks for your post :)

            - Tran Nam

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              December 23, 2010

              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

                Try DigitalOcean for free

                Click below to sign up and get $200 of credit to try our products over 60 days!

                Sign up

                Join the Tech Talk
                Success! Thank you! Please check your email for further details.

                Please complete your information!

                Become a contributor for community

                Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                DigitalOcean Documentation

                Full documentation for every DigitalOcean product.

                Resources for startups and SMBs

                The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                Get our newsletter

                Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                New accounts only. By submitting your email you agree to our Privacy Policy

                The developer cloud

                Scale up as you grow — whether you're running one virtual machine or ten thousand.

                Get started for free

                Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                *This promotional offer applies to new accounts only.