Monthly Archives: January 2013

Java Object Cloning:Cloning Java Object By Using Cloneable Interface

    Coffe_Cup   Cloning means coping a object’s internal contents to a new object which will have a different memory address. Assignment operator assigns the reference or memory address to other object.Any change made in that object will reflect in original object as well.But in cloning a new object having different reference is created.And any change made in this cloned object will not make any change in original object.So essentially cloning is object duplication having different memory address.There are several ways in Java to perform object duplication or cloning like:

1.Using Java Object class’s clone() method and Cloneable iterface

2.Using Copy Constructor

3.Using Factory Method.

4.Using Serialization

In this article ,We will discuss cloning by using first approach that is by using Object class’s clone() method and Cloneable Interface.

1.Using Java Object class’s clone() method and Cloneable iterface (Cloneable is a marker interface):

In this approach, the Java Class whose object we want to clone should have implement Cloneable interface and should override object class’s clone() method.Example class for this is(CodeSample1):

package com.devil;
/*-------------------------------------------------------------------------*/
/**
* Class which implement Cloneable interface and override object class's clone()
* method and thats why its object can be used for cloning or duplication or
* copying.This class is capable of doing Shallow Cloning only.
*
*/
/*-------------------------------------------------------------------------*/
public class NationalPark implements Cloneable{
public String name;
public String stateName;
public Integer yearOfEstablishment;
public Animal animal;
public NationalPark(String name, String stateName,
Integer yearOfEstablishment) {
this.name = name;
this.stateName = stateName;
this.yearOfEstablishment = yearOfEstablishment;
Animal animal = new Animal("Tiger", 9, "Sariska");
this.animal = animal;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
public Integer getYearOfEstablishment() {
return yearOfEstablishment;
}
public void setYearOfEstablishment(Integer yearOfEstablishment) {
this.yearOfEstablishment = yearOfEstablishment;
}
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}

The above class use another class Animal whose code is as (CodeSample2)::

package com.devil;

/*-------------------------------------------------------------------------*/
/*Animal class which is not cloneable
/*-------------------------------------------------------------------------*/

public class Animal {
public String name;
public Integer age;
public String sanctuaryName;
public Animal(String name, Integer age, String sanctuaryName) {
this.name = name;
this.age = age;
this.sanctuaryName = sanctuaryName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSanctuaryName() {
return sanctuaryName;
}
public void setSanctuaryName(String sanctuaryName) {
this.sanctuaryName = sanctuaryName;
}
}

 

 

Now lets use NationalPark class for creating cloned object.Example for this demonstration is (CodeSample3)::

package com.devil;
/*-------------------------------------------------------------------------*/
/* Code example for explaining basic cloning concept
/*-------------------------------------------------------------------------*/
public class JavaCloneExample1 {

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

NationalPark nationalPark1= new NationalPark("Sariska","Rajashthan",1955);
NationalPark nationalPark2=nationalPark1;
NationalPark clonedNationalPark1=(NationalPark) nationalPark1.clone();

System.out.println("Are object1 and object2 have same reference:- "+(nationalPark1==nationalPark2));
System.out.println("Are object1 and clone object have same reference:- "+(nationalPark1==clonedNationalPark1));
System.out.println("");

System.out.println("NationalPark object1 hashcode:-"+""+nationalPark1.hashCode());
System.out.println("NationalPark object2 hashcode:-"+""+nationalPark2.hashCode());
System.out.println("NationalPark cloned object hashcode:-"+""+clonedNationalPark1.hashCode());
System.out.println("");
}
}

 
Output  of the above code is:
 
Are object1 and object2 have same reference:- true
Are object1 and clone object have same reference:- false

NationalPark object1 hashcode:-1068505417
NationalPark object2 hashcode:-1068505417
NationalPark cloned object hashcode:-1112287305

From the above results,Cloned object has different memory address(reference)than the original object.Also since default implementation of hashcode() method(which is in Java Object class) driven by memory address,cloned object has different hashcode than that of original object.

Now what happens if  we do not override clone() method or do not implement Cloneable interface.

Well,implementing Cloneable interface can not be avoided if we want to give our class cloning capability.Lets we are not implementing Cloneable  interface in our NationalPark class(CodeSample1) and now we are trying to run our programme CodeSample3 ,Following exception will occur in the output:

java.lang.CloneNotSupportedException: com.devil.NationalPark
at java.lang.Object.clone(Native Method)
at com.devil.NationalPark.clone(NationalPark.java:30)
at com.devil.JavaCloneExample1.main(JavaCloneExample1.java:11)

Now,overriding clone() method can be avoided but of no use.It will be like we have something but we can not use.Its because if we are not overriding clone() method,It means we are using Java Object’s clone() method whose accessibility is “protected”.That means we can use this method only in the child class(in our case:NationalPark) whose base class in Object.If we will try to access this method outside(lets say in CodeSample3) of cloned class (NationalPark),

a compile error will come up saying :-”The method clone() from the type Object is not visible”.

So essence is that,Its completely necessary to implement Clone able interface for making  a class capable of cloning.And its necessary to override clone() method so that we can use cloning capability of class.

 

Now Java Cloning is of two types;Shallow copy and Deep copy which are explained as below

Shallow Copying :

Now if a java object(say NationalPark in our case) contains a reference of other objects (say Animal in our case) as well.The default cloning(as in above example) will not clone internal object(animal).Animal object reference will be same in cloned object(clonedNationalPark1) and original object(nationalPark1).So  any change made in animal object in Cloned Object will be reflected in animal object of Original Object also.This is called Shallow Copying.An example showing Shallow Copying is as:

package com.devil;
/*-------------------------------------------------------------------------*/
/* This Cloning Example demonstrates Shallow Copy
*
*
/*-------------------------------------------------------------------------*/
public class JavaCloneExample2 {
public static void main(String args[]) throws CloneNotSupportedException {
NationalPark nationalPark1= new NationalPark("Sariska","Rajashthan",1955);
NationalPark nationalPark2=nationalPark1;
NationalPark clonedNationalPark1=(NationalPark) nationalPark1.clone();
System.out.println("NationalPark object1:-"+nationalPark1.hashCode());
System.out.println("NationalPark object2:-"+nationalPark2.hashCode());
System.out.println("NationalPark cloned object:-"+clonedNationalPark1.hashCode());
System.out.println("");
Animal animal1=nationalPark1.getAnimal();
Animal animal2=clonedNationalPark1.getAnimal();
System.out.println("Are animal1 and animal2 have same reference:- "+(animal1==animal2));
System.out.println("");
//Any change in animal2 object will reflect in animal1 object as well.
animal2.setName("Elephant");
animal2.setSanctuaryName("Kajiranga");
System.out.println("NationalPark animal2 object attributes:- "+animal2.getName()+"--"+
animal2.getSanctuaryName()+"--"+animal2.getAge());
System.out.println("NationalPark animal1 object attributes:- "+animal1.getName()+"--"+
animal1.getSanctuaryName()+"--"+animal1.getAge());
}
}

The output of the above code will be as:

 

NationalPark object1:-1489230252
NationalPark object2:-1489230252
NationalPark cloned object:-570939579

Are animal1 and animal2 have same reference:- true

NationalPark animal2 object attributes:- Elephant--Kajiranga--9
NationalPark animal1 object attributes:- Elephant--Kajiranga--9

So in shallow coping internal object animal1 of original object(e.g nationalPark1) and internal object animal2 of cloned object(e.g clonedNationalPark1) points to the same memory reference.Any change made to animal2 object will reflect in animal1 object as well.So if we want to manipulate internal objects of cloned object and do not want to affect original object, we should choose Deep Copying cloning.

Deep Copying:

In Deep Copying all the internal objects which are used as an reference(e.g Animal) will also cloned with that of original object(e.g NationalPark).So in deep copying we will get a complete cloned object which can be changed anyhow without affecting the original object.If we want  a deep copy of cloned object,Following things should be keep in mind:

1. All the internal object which are used as an reference (e.g Animal) should implement Cloneable interface.

2.All the internal objects which are used as an reference (e.g Animal)should override clone()

method of Java Object class.

 

So w.r.t above example,If we want to make Deep Cloning of NationalPark object.We have to change Animal class as per above two points which will be as:

package com.devil;
/*-------------------------------------------------------------------------*/
/* Animal class which is Cloneable
/*-------------------------------------------------------------------------*/
public class Animal implements Cloneable {
public String name;
public Integer age;
public String sanctuaryName;
public Animal(String name, Integer age, String sanctuaryName) {
this.name = name;
this.age = age;
this.sanctuaryName = sanctuaryName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSanctuaryName() {
return sanctuaryName;
}
public void setSanctuaryName(String sanctuaryName) {
this.sanctuaryName = sanctuaryName;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
 
Last step will be to make change in Clone() method of the original object (NationalPark) so that internal objects are also cloneable.So the modified NationalPark class(only change is in clone() method) will be as:
 
package com.devil;
/*-------------------------------------------------------------------------*/
/*
* Class which implement Cloneable interface and override object class's clone()
* method and thats why its object can be used for cloning or duplication or
* copying.This Class is capable of doing Deep Cloning
*
*/
/*-------------------------------------------------------------------------*/
public class NationalPark implements Cloneable {
public String name;
public String stateName;
public Integer yearOfEstablishment;
public Animal animal;
public NationalPark(String name,String stateName,Integer yearOfEstablishment){
this.name=name;
this.stateName=stateName;
this.yearOfEstablishment=yearOfEstablishment;
Animal animal=new Animal("Tiger",9,"Sariska");
this.animal=animal;
}
//Clone() method implementation for Deep Cloning
@Override
protected Object clone() {
try {
NationalPark nationalPark= (NationalPark) super.clone();
nationalPark.animal=(Animal) this.animal.clone();
return nationalPark;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
public Integer getYearOfEstablishment() {
return yearOfEstablishment;
}
public void setYearOfEstablishment(Integer yearOfEstablishment) {
this.yearOfEstablishment = yearOfEstablishment;
}
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
Below example demonstrate Deep Copying by using above class:
 
 
package com.devil;
/*------------------------------------------------------------------------------*/
/* This Cloning Example demonstrates Deep Copy
*
*
/*-----------------------------------------------------------------------------*/
public class JavaCloneExample3 {
public static void main(String args[]) throws CloneNotSupportedException {
NationalPark nationalPark1= new NationalPark("Sariska","Rajashthan",1955);
NationalPark nationalPark2=nationalPark1;
NationalPark clonedNationalPark1=(NationalPark) nationalPark1.clone();
System.out.println("Are object1 and object2 have same reference:- "+
(nationalPark1==nationalPark2));
System.out.println("Are object1 and clone object have same reference:- "+
(nationalPark1==clonedNationalPark1));
System.out.println("");

System.out.println("NationalPark object1:-"+nationalPark1.hashCode());
System.out.println("NationalPark object2:-"+nationalPark2.hashCode());
System.out.println("NationalPark cloned object:-"+clonedNationalPark1.hashCode());
System.out.println("");

Animal animal1=nationalPark1.getAnimal();
Animal animal2=clonedNationalPark1.getAnimal();
System.out.println("Are animal1 and animal2 have same reference:- "+(animal1==animal2));

System.out.println("");
//Any change in animal2 object will not reflect in animal1 object.
animal2.setName("Elephant");
animal2.setSanctuaryName("Kajiranga");
System.out.println("NationalPark animal2 object attributes:- "+animal2.getName()+"--"+
animal2.getSanctuaryName()+"--"+animal2.getAge());
System.out.println("NationalPark animal1 object attributes:- "+animal1.getName()+"--"+
animal1.getSanctuaryName()+"--"+animal1.getAge());
}
}

 

Output of the above code is as:

Are object1 and object2 have same reference:- true
Are object1 and clone object have same reference:- false

NationalPark object1:-1004958336
NationalPark object2:-1004958336
NationalPark cloned object:-375869497

Are animal1 and animal2 have same reference:- false

NationalPark animal2 object attributes:- Elephant--Kajiranga--9
NationalPark animal1 object attributes:- Tiger--Sariska--9
Above output clearly shows that animal1 and animal2 are having difference memory reference.Any change made in the animal2 object will not affect animal1 object and so original NationalPark object .So this was the Deep Copying.
 
One of the major application of using cloned object is for creating defensive copy in designing  of a immutable class.
 
 
So after reading this article ,you should be able to know the answer for the following questions:
 
1.What is Java Object Cloning or Java Cloning.And what is its uses ?

2.What is the use of Java Object clone() method.?

3.What is the use of Cloneable interface?

4.What is Shallow Cloning (or Shallow Copy) and Deep Cloning(or Deep Copy).?
What is the difference between these two types of cloning.?

5.When we should use Shallow Copy and when we should use Deep Copy.?