Tuesday 21 October 2014

How Clone method works in JAVA...???

What is clone of object in Java

An object which is returned by clone() method is known as clone of original instance. A clone object should follow basic characteristics e.g. a.clone() != a, which means original and clone are two separate object in Java heap, a.clone().getClass() == a.getClass() and clone.equals(a), which means clone is exact copy of original object. These characteristic is followed by a well behaved, correctly overridden clone() method in Java, but it's not enforced by cloning mechanism. Which means, an object returned by clone() method may violate any of these rules. By following convention of returning object by calling super.clone(), when overriding clone() method, you can ensure that it follows first two characteristics. In order to follow third characteristic, you must override equals method to enforce logical comparison, instead of physical comparison exists in java.lang.Object. For example, clone() method of Rectangle class in this method return object, which has these characteristics, but if you run same program by commenting equals(), you will see that third invariant i.e. clone.equals(a) will return false. By the way there are couple of good items on Effective Java regarding effective use of clone method, I highly recommend to read those items after going through this article.

How Clone method works in Java

java.lang.Object provides default implementation of clone() method in Java. It's declared as protected and native in Object class, so implemented in native code. Since it's convention to return clone() of object by calling super.clone() method, any cloning process eventually reaches to java.lang.Object clone() method. This method, first checks if corresponding object implements Cloneableinterface, which is a marker interface. If that instance doesn't implements Cloneable then it throws CloneNotSupported in Java, a checked exception, which is always required to be handled while cloning an object. If object pass this check, than java.lang.Object's clone() method creates a shallow copy of object and returned it to the caller. Since Object class' clone() method creates copy by creating new instance, and then copying field-by-field, similar to assignment operator, it's fine for primitives and Immutable object, but not suited if your class contains some mutable data-structure e.g. Collection classes like ArrayList or arrays. In that case, both original object and copy of object will point to the same object in heap. You can prevent this by using technique known as deep cloning, on which each mutable field is cloned separately. In short, here is how clone method works in Java :

1) Any class calls clone() method on instance, which implements Cloneable and overrides protected clone() method from Object class, to create a copy.

  Rectangle rec = new Rectangle(3060);
  logger.info(rec);
      
    try {
         logger.info("Creating Copy of this object using Clone method");
         Rectangle copy = rec.clone();
         logger.info("Copy " + copy);
          
    } catch (CloneNotSupportedException ex) {
         logger.debug("Cloning is not supported for this object");
    }

2) Call to clone() method on Rectangle is delegated to super.clone(), which can be a custom super class or by default java.lang.Object

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

3) Eventually call reaches to java.lang.Object's clone() method, which verify if corresponding instance implements Cloneable interface, if not then it throws CloneNotSupportedException, otherwise it creates a field-by-field copy of instance of that class and returned to caller.

So in order for clone() method to work properly, two things need to happen, a Class should implement Cloneable interface and should override clone() method of Object class. By the way this was the simplest example of overriding clone method and how it works, things gets more complicated with real object, which contains mutable fields, arrays, collections, Immutable object and primitives.

Key Points to remember...

  1. Clone method is used to create a copy of object in Java. In order to use clone() method, class must implement java.lang.Cloneable interface and override protected clone() method from java.lang.Object. A call to clone() method will result in CloneNotSupportedException, if that class doesn't implement Cloneable interface.
  2. No constructor is called during cloning of Object in Java.
  3. Default implementation of clone() method in Java provides "shallow copy" of object, because it creates copy of Object by creating new instance and then copying content by assignment, which means if your Class contains a mutable field, then both original object and clone will refer to same internal object. This can be dangerous, because any change made on that mutable field will reflect in both original and copy object. In order to avoid this, override clone() method to provide deep copy of object.

No comments:

Post a Comment