Thursday 11 May 2017

Java Object Cloning

Object Cloning in Java

clone is an exact copy of the original. In java, it essentially means the ability to create an object with similar state as the original object. The clone() method provides this functionality.

The java.lang.Cloneable interface must be implemented by the class whose clone object wants to create. If Cloneable interface is not implemented, clone() method generates CloneNotSupportedException.

protected Object clone() throws CloneNotSupportedException  

Facts about cloning

By default, java cloning is ‘field by field copy’ i.e. as the Object class does not have idea about the structure of class on which clone() method will be invoked. So, JVM when called for cloning, do following things:

1) 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.

2) 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.

Facts behind cloning

1) You must implement Cloneable interface.
2) You must override clone() method from Object class. [Its weird. clone() method should have been in Cloneable interface.]

/*
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  [More ...] 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.

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;
       }
      
       /** Shallow copy. */
       /*@Override
       protected Object clone() throws CloneNotSupportedException {
              return super.clone();
       }*/
      
       /** Deep copy. */
       @Override
       protected Object clone() throws CloneNotSupportedException {
           Employee cloned = (Employee)super.clone();
           cloned.setDepartment((Department)cloned.getDepartment().clone());
           return cloned;
       }

       /** setters and getters. */
}

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

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

       /** for deep copy. */
       @Override
       protected Object clone() throws CloneNotSupportedException {
              return super.clone();
       }
      /** setters and getters. */
}

public class TestCloning {
        
    public static void main(String[] argsthrows 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());


        //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));
    }
}

7 comments:

  1. protected native Object clone() throws CloneNotSupportedException;
    protected method of Object class.

    So it mandatory to Override it.



    public class CloneTest {
    public static void main(String[] args) throws CloneNotSupportedException {
    CloneTest obj = new CloneTest();
    CloneTest clonedObj = (CloneTest) obj.clone();
    if(obj==clonedObj) {
    System.out.println("equal");
    } else {
    System.out.println("cloned new instanse");
    }
    }
    }

    Exception:
    Exception in thread "main" java.lang.CloneNotSupportedException: com.clone.CloneTest
    at java.lang.Object.clone(Native Method)
    at com.clone.CloneTest.main(CloneTest.java:6)

    ReplyDelete
    Replies
    1. If Clonable interface is implemented without clone() method Overriding,
      There will be deafault cloning with Shallow copy.

      public class CloneTest implements Cloneable {
      public static void main(String[] args) throws CloneNotSupportedException {
      CloneTest obj = new CloneTest();
      CloneTest clonedObj = (CloneTest) obj.clone();
      if(obj==clonedObj) {
      System.out.println("equal");
      } else {
      System.out.println("cloned new instanse");
      }
      }
      }

      cloned new instanse

      Delete
    2. If you want to perform cloning, it is must to implement the Cloneable interface.
      clone() method overriding needed when you want to perform Deep copy !!

      Delete
  2. If the Clonable (Marker interface) interface is not implemented, there will be an exception. because JVM will unable to understand that its an clonable object !

    public class CloneTest {
    public static void main(String[] args) throws CloneNotSupportedException {
    CloneTest obj = new CloneTest();
    CloneTest clonedObj = (CloneTest) obj.clone();
    if(obj==clonedObj) {
    System.out.println("equal");
    } else {
    System.out.println("cloned new instanse");
    }


    }

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

    Exception in thread "main" java.lang.CloneNotSupportedException: com.clone.CloneTest
    at java.lang.Object.clone(Native Method)
    at com.clone.CloneTest.clone(CloneTest.java:18)
    at com.clone.CloneTest.main(CloneTest.java:6)




    ReplyDelete
    Replies
    1. public class CloneTest implements Cloneable {
      public static void main(String[] args) throws CloneNotSupportedException {
      CloneTest obj = new CloneTest();
      CloneTest clonedObj = (CloneTest) obj.clone();
      if(obj==clonedObj) {
      System.out.println("equal");
      } else {
      System.out.println("cloned new instanse");
      }


      }

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

      Output :
      loned new instanse

      Delete
  3. Well explained object cloning in java . Thanks very much for sharing good article. There is also good resource for java
    clone visit Object Cloning in java

    ReplyDelete

Related Posts Plugin for WordPress, Blogger...