Cloning objects in java

Shallow Copy

Generally clone method of an object, creates a new instance of the same class and copies all the fields to the new instance and returns it. This is nothing but shallow copy. Object class provides a clone method and provides support for the shallow copy. It returns ‘Object’ as type and you need to explicitly cast back to your original object.

Since the Object class has the clone method (protected) you cannot use it in all your classes. The class which you want to be cloned should implement clone method and overwrite it. It should provide its own meaning for copy or to the least it should invoke the super.clone(). Also you have to implement Cloneable marker interface or else you will get CloneNotSupportedException. When you invoke the super.clone() then you are dependent on the Object class’s implementation and what you get is a shallow copy.

Deep Copy

When you need a deep copy then you need to implement it yourself. When the copied object contains some other object its references are copied recursively in deep copy. When you implement deep copy be careful as you might fall for cyclic dependencies. If you don’t want to implement deep copy yourselves then you can go for serialization. It does implements deep copy implicitly and gracefully handling cyclic dependencies.

One more disadvantage with this clone system is that, most of the interface / abstract class writers in java forget to put a public clone method. For example you can take List. So when you want to clone their implementations you have to ignore the abstract type and use actual implementations like ArrayList by name. This completely removes the advantage and goodness of abstractness.

When implementing a singleton pattern, if its superclass implements a public clone() method, to prevent your subclass from using this class’s clone() method to obtain a copy overwrite it and throw an exception of type  CloneNotSupportedException.

Note that clone is not for instantiation and initialization. It should not be synonymously used as creating a new object. Because the constructor of the cloned objects may never get invoked in the process. It is about copying the object in discussion and not creating new. It completely depends on the clone implementation. One more disadvantage (what to do there are so many), clone prevents the use of final fields. We have to find roundabout ways to copy the final fields into the copied object.

Clone is an agreement between you, compiler and implementer. If you are confident that you all three have good knowledge of java, then go ahead and use clone. If you have a slightest of doubt better copy the object manually.

Clone.java

package taher.clone;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author taher
 */
public class Clone implements  Cloneable{

    private String name;
    public static void main(String[] args) {
        try {
            Clone clone1 = new Clone();
            clone1.name="taher";
            System.out.println("1 : "+clone1.hashCode());
            System.out.println("name "+clone1.name);

            
            Clone clone2 = (Clone) clone1.clone();
            System.out.println("2 : "+clone2.hashCode());
            System.out.println("name a "+clone2.name);
            clone2.name="tinwala";
            System.out.println("name b "+clone2.name);
            System.out.println("name c "+clone1.name);
        } catch (CloneNotSupportedException ex) {
            Logger.getLogger(Clone.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    
}
Output :

1 : 4072869
name taher
2 : 1671711
name a taher
name b tinwala
name c taher

NoClone.java


package taher.clone;

/**
 *
 * @author taher
 */
public class NoClone {

    private String name;

    public static void main(String[] args) {
        try {
            NoClone nclone1 = new NoClone();
            nclone1.name = "taher";
            System.out.println("1 : " + nclone1.hashCode());
            System.out.println("name " + nclone1.name);

            NoClone nclone2 =  nclone1;
            System.out.println("2 : " + nclone2.hashCode());
            System.out.println("name a " + nclone2.name);
            nclone2.name = "tinwala";
            System.out.println("name b " + nclone2.name);
            System.out.println("name c " + nclone1.name);
        } catch (Exception ex) {
            System.out.println(ex);
        }
    }
}
Output :

1 : 1671711
name taher
2 : 1671711
name a taher
name b tinwala
name c tinwala

Advertisements
This entry was posted in Core JAVA, SCJP. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s