Complete Tutorial Java Cloning with Example

In general, cloning means creation of new one with exact behavior of existing one.  In Java also we can create a new object by cloning mechanism. So in this tutorial we will see about Java Cloning with Example.

Difference between cloning and copying in Java

Before we discuss about cloning, we should know the difference between cloning and copying in Java. In copying if we make any change in the cloned object then the original object also will be affected. But in cloning mechanism we can avoid this problem. Let’s see an example of copying first.

Example of copying in java

User.java

package com.learnfromexamples.clone.partone;

public class User{

    private int userNo;
    private String userName;
    public User() {
        System.out.println("User Constructor Called");
    }
    
    //setters and getters
        
    @Override
    public String toString() {
        return "User [userNo=" + userNo + ", userName=" + userName + "]";
    }
}

CloneDemoOne.java

package com.learnfromexamples.clone.partone;

public class CopyDemoOne {

    public static void main(String[] args) throws CloneNotSupportedException {
        User user = new User();
        user.setUserNo(1);
        user.setUserName("Sridhar");
        System.out.println("Before Copying");
        System.out.println(user);
        User userCopy = user;
        userCopy.setUserNo(2);
        System.out.println("After Copying");
        System.out.println(user);
        System.out.println(userCopy);
    }
}

Output

User Constructor Called
Before Copying
User [userNo=1, userName=Sridhar]
After Copying
User [userNo=2, userName=Sridhar]
User [userNo=2, userName=Sridhar]

Java Cloning

In the above example, we could see that change in Copied object also affects the Original object. To avoid that we should use cloning mechanism.

Before going to see an example, let me summarize some important points about Java cloning. Java cloning creates new object by coping every field from a class. We can also say Java cloning as “field by field copy“. In Java cloning mechanism, we have to remember two important things.

  • Copy by value – If a class contains primitive field, then new copy of object will be created and the reference to the object will be returned.
  • Copy by reference – If a class contains mutable object, then address of mutable object will be returned.

Below diagram will explain clearly about these two points.

Swallow Copy - Java Cloning with Example

Swallow Copy – Java Cloning with Example

So in cloned object if we make any change in primitive data type then original object will not be affected. But if any change in mutable field it will affect the original object as well.

How to clone Java Object

There are some rules to follow to clone the Java object.

  1. Class must Implement cloneable interface
  2. Override clone method.

We must have to follow above two rules to clone a Java Object.

#1 Java Cloning – Good to Know

Cloneable interface is a marker interface which doesn’t contain any method.

#2 Java Cloning – Good to Know

CloneNotSupportedException will be thrown if we didn’t implement Cloneable interface.

#3 Java Cloning – Good to Know

Clone method is available in Object class.

From the cloned object we could see three important conclusions as well.

  1. clone() !=x
  2. clone().getClass() ==x.getClass()
  3. clone().equals(x)

x.clone() !=x says that cloned object and original object not belongs to same memory address.  x.clone().getClass() ==x.getClass() says that cloned object and original object belongs to same type but this is not absolute requirement.  x.clone().equals(x) says the content of cloned object and original object are same but sometimes it will not be same. In order satisfy that we have to override equals method as well. We will see that from an example.

Example of Cloning in Java

User.java

package com.learnfromexamples.clone.partTwo;

public class User implements Cloneable{

    private int userNo;
    private String userName;
    private Story story;
    public User() {
        System.out.println("User Constructor Called");
    }
    //getters and setters
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "User [userNo=" + userNo + ", userName=" + userName + ", story=" + story + "]";
    }
}

Story.java

package com.learnfromexamples.clone.partTwo;

public class Story {
    
    private String storyName;
    public Story() {
        System.out.println("Story Constructor");
    }
    //getters and setters
    @Override
    public String toString() {
        return "Story [storyName=" + storyName + "]";
    }
}

CloneDemo.java

package com.learnfromexamples.clone.partTwo;

public class CloneDemo {

    public static void main(String[] args) throws CloneNotSupportedException {
        Story story = new Story();
        story.setStoryName("Harry Potter");
        User user = new User();
        user.setUserNo(1);
        user.setUserName("Sridhar");
        user.setStory(story);
        User userCloned = (User) user.clone();
        System.out.println(user);
        System.out.println(userCloned);
        
        System.out.println(user==userCloned);
        System.out.println(user.getClass()==userCloned.getClass());
        System.out.println(user.equals(userCloned));
    }

}

Output

Story Constructor
User Constructor Called
User [userNo=1, userName=Sridhar, story=Story [storyName=Harry Potter]]
User [userNo=1, userName=Sridhar, story=Story [storyName=Harry Potter]]
false
true
false

Key Points from the above example

  • User class implements Cloneable interface which tell the JVM that this object is ready for cloning.
  • Override Object clone method; tell JVM to return copy of an object.
  • clone() copies our superclass fields as well.

#4 Java Cloning – Good to Know

                Constructor will not be called during object cloning mechanism

I have already told that Java Cloning is both Copy by Value and Copy by Reference. Now we will see an example by changing the cloned object.

CloneDemo.java

package com.learnfromexamples.clone.partTwo;

public class CloneDemo {

    public static void main(String[] args) throws CloneNotSupportedException {
        Story story = new Story();
        story.setStoryName("Harry Potter");
        User user = new User();
        user.setUserNo(1);
        user.setUserName("Sridhar");
        user.setStory(story);
        User userCloned = (User) user.clone();
        System.out.println("After Modifying the cloned object");
        userCloned.setUserNo(2);
        userCloned.setUserName("Sridharan N");
        userCloned.getStory().setStoryName("Harry Potter Part Two");
        System.out.println(user);
        System.out.println(userCloned);
        
        
    }

}

Output

Story Constructor
User Constructor Called
After Modifying the cloned object
User [userNo=1, userName=Sridhar, story=Story [storyName=Harry Potter Part Two]]
User [userNo=2, userName=Sridharan N, story=Story [storyName=Harry Potter Part Two]]

Key Points from the above example

  • If we change primitives and immutable field of cloned object then original object will not be affected because that is Copy by value.
  • If we change mutable field of cloned object then original object will be affected because that is copy by reference. Refer above image.

We will call this cloning type as Swallow Copy. In order to avoid this, we have to do deep cloning of an object. We have to make the Story object as cloneable one. Let us see the updated code to avoid this problem.

Story.java

package com.learnfromexamples.clone.partTwo;

public class Story implements Cloneable{
    
    private String storyName;
    public Story() {
        System.out.println("Story Constructor");
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    
    @Override
    public String toString() {
        return "Story [storyName=" + storyName + "]";
    }
}

User.java

package com.learnfromexamples.clone.partTwo;

public class User implements Cloneable{

    private int userNo;
    private String userName;
    private Story story;
    public User() {
        System.out.println("User Constructor Called");
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        User user = (User) super.clone();
        user.story=(Story)story.clone();
        return user;
    }
    @Override
    public String toString() {
        return "User [userNo=" + userNo + ", userName=" + userName + ", story=" + story + "]";
    }
}

Now if we run the CloneDemo.java we will get the output as

Story Constructor
User Constructor Called
After Modifying the cloned object
User [userNo=1, userName=Sridhar, story=Story [storyName=Harry Potter]]
User [userNo=2, userName=Sridharan N, story=Story [storyName=Harry Potter Part Two]]

Key Points from the above example

  • We have implemented Cloneable interface for Story object and overriding the clone method.
  • In User class clone method, we have called Story clone method.

We have seen only half of the concepts about Java Cloning. We have lot to discuss about this concept. I will write some advanced concept about Java Cloning in my next tutorial also.

If  you like this tutorial please share it with your friends and provide your feedback by providing comment. If you have any queries also please comment your questions below.