Java Cloning – Deep and Shallow Copy – Copy Constructors

In Java, cloning is the process of creating an exact copy of the original object. It essentially means the ability to create an object with a similar state as the original object.

The Object’s clone() method provides the cloning functionality in Java.

1. What is Cloning in Java?

In simple words, cloning is about creating a copy of the original object. Its dictionary meaning is: “make an identical copy of”.

By default, Java cloning is ‘field by field copy’ because the Object class does not have any idea about the structure of the class on which the clone() method will be invoked.

So, JVM when called for cloning, does the following things:

  • If the class has only primitive data type members then a completely new copy of the object will be created and the reference to the new object copy will be returned.
  • If the class contains members of any class type then only the object references to those members are copied and hence the member references in both the original object as well as the cloned object refer to the same object.

Apart from the above default behavior, we can always override this behavior and specify your own. This is done by overriding the clone() method. Let’s see how it is done.

2. Cloneable Interface and clone() Method

2.1. Rules

In java, if a class needs to support cloning, we must do the following things:

  1. We must implement Cloneable interface.
  2. We must override clone() method from Object class.(It is weird. clone() method should have been in Cloneable interface.)

Read more: Cloneable interface is broken in java

Java docs about clone() method are given below (formatted and extracted).

/**
Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object.
The general intent is that, for any object x, the expression:
1) x.clone() != x will be true
2) x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.
3) x.clone().equals(x) will be true, this is not an absolute requirement.
*/

protected native Object clone() throws CloneNotSupportedException;
  1. First statement guarantees that cloned object will have separate memory address assignment.
  2. Second statement suggests that original and cloned objects should have same class type, but it is not mandatory.
  3. Third statement suggests that original and cloned objects should have be equal using equals() method, but it is not mandatory.

2.2. Example

Let’s understand the Java cloning process with an example. The Employee class has 3 fields – id, name and department.

public class Employee implements Cloneable {

	private int empoyeeId;
	private String employeeName;
	private Department department;

	public Employee(int id, String name, Department dept)
	{
		this.empoyeeId = id;
		this.employeeName = name;
		this.department = dept;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}

	//Getters and Setters
}

Department class has two attributes – id and name.

public class Department
{
	private int id;
	private String name;

	public Department(int id, String name)
	{
		this.id = id;
		this.name = name;
	}

	//Getters and Setters
}

So, if we need to clone the Employee class, then we need to do something like this.

public class TestCloning
{

	public static void main(String[] args) throws CloneNotSupportedException
	{
		Department dept = new Department(1, "Human Resource");
		Employee original = new Employee(1, "Admin", dept);

		//Lets create a clone of original object
		Employee cloned = (Employee) original.clone();

		//Let verify using employee id, if cloning actually workded
		System.out.println(cloned.getEmpoyeeId());

		//Verify JDK's rules

		//Must be true and objects must have different memory addresses
		System.out.println(original != cloned);

		//As we are returning same class; so it should be true
		System.out.println(original.getClass() == cloned.getClass());

		//Default equals method checks for references so it should be false. If we want to make it true,
		//then we need to override equals method in Employee class.
		System.out.println(original.equals(cloned));
	}
}
1
true
true
false

Great, we successfully cloned the Employee object. But, remember we have two references to the same object and now both will change the state of the object in different parts of the application. Want to see how? Let’s see.

public class TestCloning {

	public static void main(String[] args) throws CloneNotSupportedException {

		Department hr = new Department(1, "Human Resource");

		Employee original = new Employee(1, "Admin", hr);
		Employee cloned = (Employee) original.clone();

		//Let change the department name in cloned object and we will verify in original object
		cloned.getDepartment().setName("Finance");

		System.out.println(original.getDepartment().getName());
		System.out.println(cloned.getDepartment().getName());
	}
}
Finance
Finance

Oops, cloned object changes are visible in the original also. This way cloned objects can make havoc in the system if allowed to do so. Anybody can come and clone your application objects and do whatever he likes. Can we prevent this??

The answer is yes, we can. We can prevent this by creating deep copying or using copy constructors. We will learn about them later in this post.

3. Shallow Copy of an Object

Shallow cloning is the “default implementation” in Java. In overridden clone() method, if we are not cloning all the object types (not primitives), then we are making a shallow copy.

All above examples are of shallow copy only, because we have not cloned the Department object on Employee class’s clone method. Now, I will move on to the next section where we will see the deep cloning.

4. Deep Copying in Java

Deep cloning or deep copying is the desired behavior in most cases. In the deep copy, we create a clone that is independent of the original object and making changes in the cloned object should not affect the original object.

Let’s see how deep copy is created in Java.

//Modified clone() method in Employee class
@Override
protected Object clone() throws CloneNotSupportedException {
	Employee cloned = (Employee)super.clone();
	cloned.setDepartment((Department)cloned.getDepartment().clone());
	return cloned;
}

I modified the Employee classes clone() method and added following clone method in Department class.

//Defined clone method in Department class.
@Override
protected Object clone() throws CloneNotSupportedException {
	return super.clone();
}

Now testing our cloning code gives the desired result and the name of the department will not be modified in the clone object.

public class TestCloning
{
	public static void main(String[] args) throws CloneNotSupportedException
	{
		Department hr = new Department(1, "Human Resource");

		Employee original = new Employee(1, "Admin", hr);
		Employee cloned = (Employee) original.clone();

		//Let change the department name in cloned object and we will verify in original object
		cloned.getDepartment().setName("Finance");

		System.out.println(original.getDepartment().getName());
		System.out.println(cloned.getDepartment().getName());
	}
}
Human Resource
Finance

Here, changing the state of the cloned object does not affect the original object.

So deep cloning requires satisfaction of following rules –

  • No need to separately copy primitives.
  • All the member classes in original class should support cloning and in clone method of original class in context should call super.clone() on all member classes.
  • If any member class does not support cloning then in clone method, one must create a new instance of that member class and copy all its attributes one by one to new member class object. This new member class object will be set in cloned object.

Read more: Deep cloning using in-memory serialization

5. Copy Constructors

Copy constructors are special constructors in a class that takes an argument for its own class type.

So, when you pass an instance of a class to a copy constructor, the constructor will return a new instance of the class with values copied from the argument instance. It helps us to clone objects without the Cloneable interface.

5.1. Example

Let us see an example of the copy constructors.

public class PointOne
{
	private Integer x;
	private Integer y;

	public PointOne(PointOne point){
		this.x = point.x;
		this.y = point.y;
	}
}

5.2. Watch out for Inheritance Issues

Above class PointOne looks simple and it is until comes inheritance.

When we define a child class by extending the above class, we need to define a similar constructor there also. In child class, we need to copy child-specific attributes and pass the argument to the super class’s constructor.

Let’s see how.

public class PointTwo extends PointOne
{
	private Integer z;

	public PointTwo(PointTwo point){
		super(point); //Call Super class constructor here
		this.z = point.z;
	}
}

So, are we fine now? NO. The problem with inheritance is that exact behavior is identified only at runtime.

So, in our case, if some class passed the instance of PointTwo in constructor of PointOne. In this case, we will get the instance of PointOne in return where we passed the instance of PointTwo as an argument.

Let us see this in code:

public class Test
{
	public static void main(String[] args)
	{
		PointOne one = new PointOne(1,2);
		PointTwo two = new PointTwo(1,2,3);

		PointOne clone1 = new PointOne(one);
		PointOne clone2 = new PointOne(two);

		//Let check for class types
		System.out.println(clone1.getClass());
		System.out.println(clone2.getClass());
	}
}
class corejava.cloning.PointOne
class corejava.cloning.PointOne

6. Static Factory Methods

Another way of creating a copy constructor is to have static factory methods. They take the class type in the method argument and create a new instance using another constructor of the class.

Then these factory methods will copy all the state data to the new class instance just created in the previous step, and return this updated instance.

public class PointOne implements Cloneable
{
	private Integer x;
	private Integer y;

	public PointOne(Integer x, Integer y)
	{
		this.x = x;
		this.y = y;
	}

	public static PointOne copyPoint(PointOne point) throws CloneNotSupportedException
	{
		if(!(point instanceof Cloneable))
		{
			throw new CloneNotSupportedException("Invalid cloning");
		}

		//Can do multiple other things here
		return new PointOne(point.x, point.y);
	}
}

7. Deep Cloning with Serialization

Serialization is another easy way of deep cloning. In this method, we serialize the object to be cloned and de-serialize it back. Obviously, the object, that needs to be cloned, should implement Serializable interface.

Before going any further, I should caution that this technique is not to be used lightly.

  1. First of all, serialization is hugely expensive. It could easily be a hundred times more expensive than the clone() method.
  2. Second, not all objects are Serializable.
  3. Third, making a class Serializable is tricky and not all classes can be relied on to get it right.

Read more: A guide to implement serialization in Java

@SuppressWarnings("unchecked")
public static T clone(T t) throws Exception {
	//Check if T is instance of Serializeble other throw CloneNotSupportedException
	ByteArrayOutputStream bos = new ByteArrayOutputStream();

	//Serialize it
	serializeToOutputStream(t, bos);
	byte[] bytes = bos.toByteArray();
	ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));

	//Deserialize it and return the new instance
	return (T)ois.readObject();
}

8. Cloning with Apache Commons

In Apache commons, SerializationUtils class also has a utility function for deep cloning. If you feel interested follow their official docs.

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.7</version>
</dependency>
SomeObject cloned = SerializationUtils.clone(someObject);

9. Best Practices

  • When you don’t know whether you can call the clone() method of a particular class as you are not sure if it is implemented in that class, you can check with checking if the class is instance of “Cloneable” interface as below.
//We can do this
if(obj1 instanceof Cloneable){
    obj2 = obj1.clone();
}
 
//Don't do this. Cloneable does not have any methods
obj2 = (Cloneable) obj1.clone();
  • Note that no constructor is called on the Object during cloning process. As a result, it is your responsibility, to make sure all the instance fields have been properly set.
  • Also, if you are keeping track of the number of objects in the system by counting the invocation of constructors, you got a new additional place to increment the counter.

I hope that this post has been a refresher for you and helped you gain more information about Java clone method and its correct usage. It will also help in replying to Java clone interview questions.

Happy Learning !!

Leave a Comment

  1. I have a question regarding the copy constructor, I did exactly as the one you presented and i got an error line when I passed the Integer values as arguments in the constructor after creating the objects of classes PointOne and PointTwo. This line of code
    “PointOne one = new PointOne(1,2);
    PointTwo two = new PointTwo(1,2,3);”.

    Reply
    • Yes, It’s obvious, We will get compile time error while copy the above code as it is.
      You have to add two more constructor in the code-
      public PointOne(int x, int y){ //For PointOne class constructor
      this.x = x;
      this.y=y;
      }

      public PointTwo(int x, int y, int z){ // For PointTwo class constructor
      super.x = x;
      super.y = y;
      this.z=z;
      }

      Reply
  2. So impressive. I have a question , what if Department class is also having another reference of another object and so on.. Do we need to take care manually for this chain of objects to get Deep cloned object, or any other approach we have other than serialization?
    thank you in advance.

    Reply
  3. can anyone explain this to me :

    cloned.getDepartment().setName(“Finance”);

    getDepartment() method belongs to which class and setName() method belongs to which class since there are two classes i.e., Employee and Department. Also, can anyone show me the Structure of these methods and how to pass on the argument “finance” to the setName() method

    Reply
    • Employee.java

      public class Employee implements Cloneable {
      
      	private int empoyeeId;
      	private String employeeName;
      	private Department department;
      
      	public Employee(int id, String name, Department dept) {
      		this.empoyeeId = id;
      		this.employeeName = name;
      		this.department = dept;
      	}
      
      	@Override
      	protected Object clone() throws CloneNotSupportedException {
      		return super.clone();
      	}
      
      	public int getEmpoyeeId() {
      		return empoyeeId;
      	}
      
      	public void setEmpoyeeId(int empoyeeId) {
      		this.empoyeeId = empoyeeId;
      	}
      
      	public String getEmployeeName() {
      		return employeeName;
      	}
      
      	public void setEmployeeName(String employeeName) {
      		this.employeeName = employeeName;
      	}
      
      	public Department getDepartment() {
      		return department;
      	}
      
      	public void setDepartment(Department department) {
      		this.department = department;
      	}
      }

      Department.java

      package com.example.howtodoinjava.dozer.simple;
      
      public class Department
      {
          private int id;
          private String name;
       
          public Department(int id, String name)
          {
              this.id = id;
              this.name = name;
          }
      
      	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;
      	}
      }
      
      Reply
  4. Good article, I always I’ve been looking for clone. In my opinion “SerializationUtils” of apache is the cleanest way to clone simple java object.

    Reply
  5. Very nice tutorial. Indeed I have got one query. In the TestCloning example above, where we are cloning the objects of Employee class to get the original object, the references got copied, not the object if this is the case, then why does original != cloned returns true?because == method returns true if both the references refers to the same object..?

    Reply
    • @isha
      clone() returns new instance of class (new object). In the example it returns new instance of Employee. Cloned Employee will have different memory address than the original Employee, thereofre original!=cloned. But: original.department == cloned.department is true.

      Reply
  6. copyPoint is not static in your example for “static factory methods”. Do you see an issue with keeping it the way you have it?

    Static method way:
    PointOne one = new PointOne(1,2);
    PointOne two = PointOne.copyPoint(one);

    Your way:
    PointOne one = new PointOne(1,2);
    PointOne two = one.copyPoint(one);

    I like your way better than the static method because you can define the copyPoint method in an interface. Your thoughts?

    Reply
    • Also, with your way you do not need to pass the object being copied. just change the return type as follows. This just seems cleaner to me and you can define in interfaces. Is there a disadvantage over having the method static?

      public PointOne copyPoint() throws CloneNotSupportedException
      {

      return new PointOne(thiS.x, this.y);
      }

      Reply
        • If there’s a subclass, say, ColoredPointOne, then this will (by inheritance) be Cloneable too, and have a public clone method. This needs to be overridden to create a proper ColoredPointOne clone. If PointOne.clone returns a PointOne object, then ColoredPointOne can’t reuse it by calling super.clone. If you use super.clone() instead of new PointOne, then Object.clone will create the object for you, and it will be of type ColoredPointOne if that is the runtime type.

          Reply
    • Why are you using my user id and email address to comment? I just received an update in my email after someone commented on your comment.

      Reply
  7. Hi Lokesh,
    This new look to your blog is making very difficult to search topics under one category.
    Pls suggest way to browse thru all core java topics as you had in the earlier look. there is no search button too on this home page that can take me to the right location.

    Reply
  8. Hi Lokesh,

    I have a doubt that If we call clone() method on any object, Constructor will be called for that or not?

    Thanks,
    H Singh

    Reply
  9. Hi Lokesh,
    Thanks for the information. nice post.
    I am not really sure what problem do you see with following lines you mentioned.
    PointOne clone1 = new PointOne(one);
    PointOne clone2 = new PointOne(two);
    In the second line, even though object ‘two’ is passed the object being created is PointOne. I don’t see any problem with it.

    Thanks
    Ramesh

    Reply
  10. Correct me if I am wrong , but I would like to make some observations on the paragraph “Deep cloning”.
    First : I think you should declare class Department as implementing Cloneable interface , since you invoke
    method clone in class Employee row 5.
    Second : I think you should change the access modifier of method clone from class Department , from “protected” to “public” , in order to make it accessible in the same place mentioned before.
    Last : I suppose it would be worth mentioning that the two String fields involved in cloning class Employee (one inside it and one inside the underlying Department object) can be left uncloned because String class is immutable.

    Reply
    • Hey buddy, thanks for invaluable inputs.

      First: This is definitely Typo error and Department must implement Cloneable interface.

      Two: No need to make clone() method public. We are overriding it from object class, and there it is declared protected. Remember, overriden methods can not widen the scope.

      Last: You are correct. Actually, all java classes have 3 types of attributes : primitives, mutable references and immutable references. There is no need to handle primitives and immutable references, but mutable references must be explicitly cloned OR copied.

      Reply
      • So what is the output for point 2? The protected clone method in Department class cannot be called in Employee class due to access restriction:

        cloned.setDepartment((Department) cloned.getDepartment.clone());
        Protected has access only within the same class or class extending the original and here there is no such relation between Employee and Department class.
        Not clear please elaborate.

        Reply
        • We can access the protected methods in same package. In this example, Employee and Department are in the same package so it can be accessed. The important thing is that we are call the clone() method defined in the Department class. If we do not override the clone() method in Department then method will be invoked from the Object class, and that is not allowed due to access restriction.

          Reply
    • for point Second:
      The method name can be any thing. e.g. it can be myClone like below. Important point is you need to call “super.clone()” as it is.
      public Object myClone() throws CloneNotSupportedException {
      return super.clone();
      }

      now your department object will be called like
      Department clonedDeptt = existingDeptt.myClone();

      Thanks
      Manish

      Reply
      • If somebody extend your class and implement his method as “wowClone(){…}”. Would he call your super.myClone() or super.clone()… Lesson: Don’t make things complicated. If you really want to do such thing, use static method to create new instances.

        Reply
        • Thats correct Lokesh, it was to demonstrate and to clear the confusions among people who thinks that we are overriding clone method that is written in Object class.

          Thanks,
          Manish

          Reply
          • So you mean to say… the Department Class does not over ride clone method, it is just a syntax? Is it correct??

Leave a Comment

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode