Java Clone

Hello guys!! Welcome to flower brackets blog. Today we are going to learn java clone.

java clone

Cloning Method

Cloning method is one of the method of object class. Object cloning is nothing but creating a copy or duplicating an object using clone method.

Clone method in java is protected in Object class and hence we should override it as public in derived classes to which we have to clone.


Types of cloning

There are two types of cloning:

  • Shallow Cloning – is a default behavior of cloning. It’s copying reference pointer to object.That is, new object is pointing to the same memory reference of the old object.

In shallow cloning memory usage is low since it creates a new instance of the same class and copies all the fields to the new instance and returns it.

  • Deep Cloning – is copy of object itself. When the copied object contains some other object it references are cloned recursively in deep cloning.

Please note that when you implement deep cloning be careful of cyclic dependencies.


Why should we use clone method?

Java clone method saves additional burden on initiating a copy of an object.

For example :

java clone

Here you can see “employeeDetailsObj” object. It has two fields Name and EmpID.

Name is George and EmpID is 458464. Using clone method we can create “clonedEmployeeDetailsObj” object and which contains same fields and same values.

Also Read – Array Java

There is no operator in java for copying an object because objects are manipulated through reference variables.

Assignment operator can be used to a create copy but it only duplicates reference not the object. Clone method can be used here.

How to clone object in java using assignment operator?

Java clone object using assignment operator will create copy of reference variable and not object. Since in java we have no operator to create copy of an object.

Now let’s see java clone example,

public class Demo 
{
   int a, b;
   Demo()
   {
      a = 20;
      b = 30;
   }
}

public class ObjectCloneJava 
{
   public static void main(String[] args) 
   {
      Demo ex1 = new Demo();
		 
      System.out.println(ex1.a + " " + ex1.b);

      // first create new reference variable ex2 pointing to same address ex1
      Demo ex2 = ex1;

      // so changes made in ex2 will be reflected in ex1
      ex2.a = 10;

      System.out.println(ex1.a + " " + ex1.b);
      System.out.println(ex2.a + " " + ex2.b);
   }
}

Output :

20 30
10 30
10 30


How to implement cloning? Java Clone

If a class or one of its superclasses implements cloneable interface you can use the clone method to create a copy from existing object.

If the object does not implement cloneable interface then if you call clone method of that particular object it will throw CloneNotSupportedException.

This is the way we can declare clone method,

Syntax

public Object clone() throws CloneNotSupportedException

or

protected Object clone() throws CloneNotSupportedException

The simplest way to make your class cloneable is to add implements cloneable to your class declaration.

Then your objects can invoke the clone method.

If the object on which clone method was invoked implement the cloneable interface, Object’s implementation of the clone method creates an object of the same class as the original object.

And initializes the new object’s member variables to have the same values as the original object’s corresponding member variables.


Example : java clone

public class Employee implements Cloneable
{
   private String empName;
   private String empID;

   public Employee(String empName, String empID)
   {
      super();
      this.empName = empName;
      this.empID = empID;
   }

   public String getEmpName()
   {
      return empName;
   }

   public void setEmpName(String empName)
   {
      this.empName = empName;
   }

   public String getEmpID()
   {
      return empID;
   }

   public void setEmpID(String empID)
   {
      this.empID = empID;
   }

   @Override
   public Object clone() throws CloneNotSupportedException
   {
      return super.clone();
   }
}

Here you can see Employee class which implements Cloneable interface. It has two fields empName and empID.

It has Employee constructor. Using this constructor we can create employee object and it has getter and setter methods for empName and empID.

Lastly I have overridden clone method (as you can see above).

public class CloneDemo
{
   public static void main(String[] args)throws CloneNotSupportedException
   {
      Employee empObj = new Employee("George", "458464");   
      System.out.println("Original Employee Details : ");  
      System.out.println("Employee Name - " + empObj.getEmpName());
      System.out.println("Employee ID - " + empObj.getEmpID());

      Employee clonedEmpObj = (Employee) empObj.clone();

      System.out.println("----------------------------------");   
      System.out.println("Cloned Employee Details : ");  
      System.out.println("Employee Name - " + clonedEmpObj.getEmpName());
      System.out.println("Employee ID - " + clonedEmpObj.getEmpID());
   }
}

As you can see above, I have defined CloneDemo. It has a main method.

First let’s see the output of above example,

java clone

As you can see in the output, I have created “empObj” object and displaying employee name and ID number.

Name is “George” and ID is 458464. Using clone method I am cloning “empObj” object and creating “clonedEmpObj” object.

Then I am displaying empName and empID of “clonedEmpObj” object. If you notice “Original Employee Details” name and ID is equal to “Cloned Employee Details” name and ID.


Shallow copy java

Now let’s try learn shallow copy in java through an example,

// student class

public class Student 
{
   private int id;
   private String name;
   private int age;

   public Student(int id, String name, int age)
   {
      System.out.println("Here we are calling Student constructor.");
      this.id = id;
      this.name = name;
      this.age = age;
   }

   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 int getAge()
   {
      return age;
   }

   public void setAge(int age)
   {
      this.age = age;
   }

   @Override
   public String toString()
   {
      return "Student [id = " + id + ", name = " + name + ", age = " + age + "]";
   }
}

// main class

public class Section 
{
   public static void main(String[] args) 
   {
      Student student1 = new Student(101, "Albert", 10);
      System.out.println("Original Student object - " + student1);
   }
}

Output :

Here we are calling Student constructor.
Original Student object - Student [id = 101, name = Albert, age = 10]

Here you can see I have Student class and Student class is having some fields. I have initialized those fields using constructor.

And we have “public” getter and setter methods. Also we have overridden toString() method to display state of objects in the nice format.

Now we have a “Section” program. Here I have created one student object by calling its parametric constructors and I have passed id, name and age.

Lastly I’m printing student object and the output will be as shown above.

Now I want to create a clone of student object.

How can we do that??

First of all if we want to create clone of an object, Student class should to implement Cloneable interface and this is the first criteria to create clone of an object.

Like this,

public class Student implements Cloneable
{

}

Cloneable interface does not have any methods. Now once Student class implements Cloneable interface we have clone method which is available in superclass that is Object class.

Also Read – 2d Array Java

We can access that by student. Here we are going to override. There are two ways we can do, they are, either we can create our own choice like myClone and call super.clone() method.

Or directly we can override the clone method, like this,

@Override
public Object clone() throws CloneNotSupportedException 
{ 
   return super.clone();
}

Here we have overridden the clone method in subclass and access modifier should be public so that we can call clone method outside the class.

If Student class does not implement Cloneable interface and if you try to call the clone method then in runtime you will get clone not supported exception.

These things we have to keep in mind. Now we have student object already and we want the clone of it.

For that we can simply call clone() method within try catch block like this,

try 
{
   Object object = student1.clone();
   Student student2 = (Student)object;
   System.out.println("Cloned Student object - " + student2);
}
catch(CloneNotSupportedException e) 
{ 
   e.printStackTrace();
}

And this will give you the generic written type object. Here I have type casted object into student object.

So Super class basically holds the object of subclass. Here’s the complete shallow copy java example,

// Student class

public class Student implements Cloneable
{
   private int id;
   private String name;
   private int age;

   public Student(int id, String name, int age)
   {
      System.out.println("Here we are calling Student constructor.");
      this.id = id;
      this.name = name;
      this.age = age;
   }

   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 int getAge()
   {
      return age;
   }

   public void setAge(int age)
   {
      this.age = age;
   }

   @Override
   public Object clone() throws CloneNotSupportedException 
   { 
      return super.clone();
   }

   @Override
   public String toString()
   {
      return "Student [id = " + id + ", name = " + name + ", age = " + age + "]";
   }
}

// main class

public class Section 
{
   public static void main(String[] args) 
   {
      System.out.println("Original Student object - ");
      Student student1 = new Student(101, "Albert", 10);
      System.out.println(student1);
      try 
      {
         Object object = student1.clone();
         Student student2 = (Student)object;
         System.out.println("Cloned Student object - " + student2);
      }
      catch(CloneNotSupportedException e) 
      { 
         e.printStackTrace();
      }
   }
}

Output :

Original Student object - 
Here we are calling Student constructor.
Student [id = 101, name = Albert, age = 10]
Cloned Student object - Student [id = 101, name = Albert, age = 10]

As you can see the output first time we created an object using “new” operator and for the second time we just cloned using Cloneable interface.


Deep copy java

Now in this segment we will learn deep cloning.

What is deep cloning?

Basically deep cloning comes into picture when the object is having another reference of another (custom) object.

In this case if you don’t want references of the object being copied during the cloning process then option is deep copy.

When deep copy is completed, objects referenced by the cloned object are distinct from those referenced by the original object and will be independent.

Deep copies are more expensive as you need to create additional object and can be substantially more complicated due to references possibly forming a complicated graph.

Let’s try to understand with an example,

// Student class

public class Student implements Cloneable
{
   private int id;
   private String name;
   private int age;

   private Address address;

   public Student(int id, String name, int age, Address address)
   {
      System.out.println("Here we are calling Student constructor.");
      this.id = id;
      this.name = name;
      this.age = age;
      this.address = address;
   }

   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 int getAge()
   {
      return age;
   }

   public void setAge(int age)
   {
      this.age = age;
   }

   public Address getAddress()
   {
      return address;
   }

   public void setAddress(Address address)
   {
      this.address = address;
   }

   @Override
   public Object clone() throws CloneNotSupportedException 
   { 
      return super.clone();
   }

   @Override
   public String toString()
   {
      return "Student [id = " + id + ", name = " + name + ", age = " + age + ", address = " + address + "]";
   }
}

// Address class

public class Address 
{
   private int id;
   private String addressOne;
   private String addressTwo;
   private String city;
   private long pinCode;

   public Address(int id, String addressOne, String addressTwo, String city, long pinCode)
   {
      this.id = id;
      this.addressOne = addressOne;
      this.addressTwo = addressTwo;
      this.city = city;
      this.pinCode = pinCode;
   }

   public int getId()
   {
      return id;
   }

   public void setId(int id)
   {
      this.id = id;
   }

   public String getAddressOne()
   {
      return addressOne;
   }

   public void setAddressOne(String addressOne)
   {
      this.addressOne = addressOne;
   }

   public String getAddressTwo()
   {
      return addressTwo;
   }

   public void setAddressTwo(String addressTwo)
   {
      this.addressTwo = addressTwo;
   }

   public String getCity()
   {
      return city;
   }

   public void setCity(String city)
   {
      this.city = city;
   }

   public long getPinCode()
   {
      return pinCode;
   }

   public void setPinCode(long pinCode)
   {
      this.pinCode = pinCode;
   }

   @Override
   public String toString() 
   { 
      return "Address [id = " + id + ", addressOne = " + addressOne + ", addressTwo = " + addressTwo + ", city = " + city + ", pincode = " + pinCode + "]";
   }
}

// main class

public class Section 
{
   public static void main(String[] args) 
   {
      Address address = new Address(401, "Lane 1", "5th cross", "Chennai", 600003);
      Student student1 = new Student(101, "Albert", 10, address);

      try 
      {
         Object object = student1.clone();
         Student student2 = (Student)object;

         System.out.println("Original Student object - ");
         System.out.println(student1);
         System.out.println("Cloned Student object - ");
         System.out.println(student2);
      }
      catch(CloneNotSupportedException e) 
      { 
         e.printStackTrace();
      }
   }
}

Output :

Here we are calling Student constructor.
Original Student object - 
Student [id = 101, name = Albert, age = 10, address = Address [id = 401, addressOne = Lane 1, addressTwo = 5th cross, city = Chennai, pincode = 600003]]
Cloned Student object - 
Student [id = 101, name = Albert, age = 10, address = Address [id = 401, addressOne = Lane 1, addressTwo = 5th cross, city = Chennai, pincode = 600003]]

As you can see we have Student class which implements Cloneable interface because we want to create and clone Student class object.

Now we have some fields primitive as well as String data type fields and we have one reference called “Address” and we have initialized in the constructor.

We have a public setter getter methods and I have overridden toString() method and also clone method which is making call to the superclass clone method.

Coming to “Section” program here we have Address and address is having some fields, public constructor and public setter getter method.

And of course I have overridden toString() method here as well. So in “Section” program what I have done is I have created an object of address.

We are passing student id, name, age and address reference which we had created. Now we want a clone of “student1”.

“student1” is the original object. Now we want the clone of student1 and that’s the reason i’m calling clone method which is already overridden in Student class.

Next we have typecasted student2 and we got the cloned object and student2 is the cloned object.

Meanwhile I’m printing original object as well as cloned object. Now we will run this application and you can see the output as shown above.

In the output you can see original as well as cloned object content is same.

Now we will go to the cloned object and make some changes, like this,

Object object = student1.clone();
Student student2 = (Student)object;
student2.setName("Daniel");
student2.getAddress().setCity("Mumbai");

After adding this code here’s the output we get,

Here we are calling Student constructor.
Original Student object - 
Student [id = 101, name = Albert, age = 10, address = Address [id = 401, addressOne = Lane 1, addressTwo = 5th cross, city = Mumbai, pincode = 600003]]
Cloned Student object - 
Student [id = 101, name = Daniel, age = 10, address = Address [id = 401, addressOne = Lane 1, addressTwo = 5th cross, city = Mumbai, pincode = 600003]]

In the above output original object name is “Albert” and cloned object is “Daniel” not a problem. We made modification in the clone object that is not reflected to original object.

Now if you look at the address content here in original object address “Mumbai” and cloned object address is also “Mumbai”.

So when I made modification in the cloned object its been reflecting in the original object and this should not happen.

If you get the cloned object, then if you do any modification in the cloned object that shouldn’t reflect in original object.

In that case shallow cloning is not achieved.

How to fix it?

Solution is deep cloning. To do that, in Student class we have to call clone method of super class,

@Override
public Object clone() throws CloneNotSupportedException 
{ 
   Student student = (Student)super.clone();
   student.setAddress(new Address(getAddress().getId(), getAddress().getAddressOne(), getAddress().getAddressTwo(), getAddress().getCity(), getAddress().getPinCode()));
   return student;
}

Rest of the code remains same. After doing some modification let’s run this program and see output,

Here we are calling Student constructor.
Original Student object - 
Student [id = 101, name = Albert, age = 10, address = Address [id = 401, addressOne = Lane 1, addressTwo = 5th cross, city = Chennai, pincode = 600003]]
Cloned Student object - 
Student [id = 101, name = Daniel, age = 10, address = Address [id = 401, addressOne = Lane 1, addressTwo = 5th cross, city = Mumbai, pincode = 600003]]

As you can see the output, original object city was Chennai and in the cloned object whatever modification we had done is not reflected in the original object.

So this issue has been fixed because of the deep cloning.


conclusion:

So that’s about java clone. I hope you have understood the concept of java clone.

You can subscribe to my blog flower brackets if haven’t already. Do share this post if you like.

You May Also Like