Thursday, June 2, 2016

Cloneable Interface in Java


Introduction

 

The object cloning is a way to create exact copy of an object. For this purpose, clone() method of Object class is used to clone an object.

The java.lang.Cloneable interface must be implemented by the class whose object clone we want to create.If we don't implement Cloneable interface, clone() method generates CloneNotSupportedException.The clone() method is defined in the Object class. 
Syntax of the clone() method is as follows:

protected Object clone() throws CloneNotSupportedException 

 

Why use clone() method

The clone() method saves the extra processing task for creating the exact copy of an object.If we perform it by using the new keyword,it will take a lot of processing to be performed that is why we use object cloning.

 

Advantage of Object cloning

Less processing task.
 
1.First statement guarantees that cloned object will have separate memory address assignment.
2.Second statement suggest that original and cloned objects should have same class type, but it is not mandatory.
3.Third statement suggest that original and cloned objects should have be equal using equals() method, but it is not mandatory.


Does clone object and original object point to the same location in memory

The answer is no. The clone object has its own space in the memory where it copies the content of the original object.
That’s why when we change the content of original object after cloning, the changes does not reflect in the clone object.



Shallow Copy

 

Whenever we use default implementation of clone method we get shallow copy of object means it create new instance and copy all the field of object to that new instance and return it as object type we need to explicitly cast it
back to our original object. This is shallow copy of the object. clone() method of the object class support shallow copy of the object. If the object contains primitive as well as non primitive or reference type variable In shallow copy,
the cloned object also refers to the same object to which the original object refers as only the object references gets copied and not the referred objects themselves. That's why the name shallow copy or shallow cloning in Java.
If only primitive type fields or Immutable objects are there then there is no difference between shallow and deep copy in Java.




Example:
In this figure, the MainObject1 have fields "field1" of int type, and "ContainObject1" of ContainObject type.When you do a shallow copy of MainObject1, MainObject2 is created with "field3" containing the copied value of
"field1" and still pointing to ContainObject1 itself. Observe here and you will find that since field1 is of primitive type, the values of it are copied to field3 but ContainedObject1 is an object, so MainObject2 is still pointing to ContainObject1. So any changes made to ContainObject1 in MainObject1 will reflect in MainObject2.



Deep Copy


Whenever we need own meaning of copy not to use default implementation we call it as deep copy, whenever we need deep copy of the object we need to implement according to our need. So for deep copy we need to ensure allthe member class also implement the Cloneable interface and override the clone() method of the object class.After that we override the clone() method in all those classes even in the classes where we have only primitivetype members otherwise we would not be able to call the protected clone() method of Object class on the instances of those classes inside some other class. It’s typical restriction of the protected access



Example:
In this figure, the MainObject1 have fields "field1" of int type, and "ContainObject1" of ContainObject type. When you do a deep copy of MainObject1, MainObject2 is created with "field3" containing the copied value of "field1" and "ContainObject2" containing the copied value of ContainObject1.So any changes made to ContainObject1 in MainObject1 will not reflect in MainObject2. 

Practical Implementation:

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;
    }
    //Accessor/mutators methods will go there
}


Employee class with 3 attributes. 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();
    }
    
    //Accessor/mutators methods will go there
}

Clone the Employee class
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 refernces so it should be false. If we want to make it true,
        //we need to override equals method in Employee class.
        System.out.println(original.equals(cloned));
    }
}

Output:
1
true
true
false


We successfully cloned the Employee object. But, remember we have two references of same object and now both will change the state of object in different parts of application.Lets 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());
    }
}
Output: Finance


Referred Sites : 

http://www.jusfortechies.com/java/core-java/deepcopy_and_shallowcopy.php 

http://java67.blogspot.in/2013/05/difference-between-deep-copy-vs-shallow-cloning-java.html
http://www.javatpoint.com/object-cloning
http://howtodoinjava.com/core-java/cloning/a-guide-to-object-cloning-in-java/


No comments:

Post a Comment