Showing posts with label clone. Show all posts
Showing posts with label clone. Show all posts

Saturday, 28 May 2011

Restrictions on clone method

There are couple of restrictions on clone methods:
  • It is a protected method and can only be called from within the same class or the module that contains the class.
  • We can only clone objects which are declared to implement the Cloneable interface.
  • Objects that cannot be cloned throw the CloneNotSupportedException.

Sunday, 17 April 2011

The clone() method in Java

Clone
Clone method is protected method of object class : protected Object clone() throws CloneNotSupportedException. This method is used to create a copy of an object of a class which implements Cloneable interface. By default it does field-by-field copy as the Object class doesn't have any idea in advance about the members of the particular class whose objects call this method. So, 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. But, 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.

Cloneable interface

We get CloneNotSupportedException if we try to call the clone() method on an object of a class which doesn't implement the Cloneable interface. This interface is a marker interface and the implementation of this interface simply indicates that the Object.clone() method can be called on the objects of the implementing class.

Example: how cloning works in Java?

Class A {
...
}
A objA = new A();
A objACloned = (A) objA.clone();

Now, objA != objACloned - this boolean expression will always be true as in any case a new object reference will be created for the cloned copy.

objA.getClass() == objACloned.getClass() - this boolean expression will also be always true as both the original object and the cloned object are instances of the same class (A in this case).

Initially, objA.equals(objACloned) will return true, but any changes to any primitive data type member of any of the objects will cause the expression to return false. It's interesting to note here that any changes to the members of the object referenced by a member of these objects will not cause the expression to return false. Reason being, both the copies are referring to same object as only the object references get copied and not the object themselves. This type of copy is called Shallow Copy (Read - Deep Copy vs Shallow Copy).

Cloning Interview questions

Q1) What are different types of cloning in Java?

Ans) Java supports two type of cloning: - Deep and shallow cloning. By default shallow copy is used in Java. Object class has a method clone() which does shallow cloning.

Q2) What is Shallow copy?

Ans) In shallow copy the object is copied without its contained objects.
Shallow clone only copies the top level structure of the object not the lower levels.
It is an exact bit copy of all the attributes.


      
Original
Figure 1: Original java object obj
The shallow copy is done for obj and new object obj1 is created but contained objects of obj are not copied.
Shallow Copy
Figure 2: Shallow copy object obj1

It can be seen that no new objects are created for obj1 and it is referring to the same old contained objects. If either of the containedObj contain any other object no new reference is created

Q3) What is deep copy and how it can be acheived?

Ans) In deep copy the object is copied along with the objects it refers to. Deep clone copies all the levels of the object from top to the bottom recursively.



Original
Figure 3 : Original Object obj
When a deep copy of the object is done new references are created.
Deep Copy
Figure 4: obj2 is deep copy of obj1

One solution is to simply implement your own custom method (e.g., deepCopy()) that returns a deep copy of an instance of one of your classes. This may be the best solution if you need a complex mixture of deep and shallow copies for different fields, but has a few significant drawbacks:

You must be able to modify the class (i.e., have the source code) or implement a subclass. If you have a third-party class for which you do not have the source and which is marked final, you are out of luck.
You must be able to access all of the fields of the class’s superclasses. If significant parts of the object’s state are contained in private fields of a superclass, you will not be able to access them.
You must have a way to make copies of instances of all of the other kinds of objects that the object references. This is particularly problematic if the exact classes of referenced objects cannot be known until runtime.
Custom deep copy methods are tedious to implement, easy to get wrong, and difficult to maintain. The method must be revisited any time a change is made to the class or to any of its superclasses.
Other common solution to the deep copy problem is to use Java Object Serialization (JOS). The idea is simple: Write the object to an array using JOS’s ObjectOutputStream and then use ObjectInputStream to reconsistute a copy of the object. The result will be a completely distinct object, with completely distinct referenced objects. JOS takes care of all of the details: superclass fields, following object graphs, and handling repeated references to the same object within the graph.

It will only work when the object being copied, as well as all of the other objects references directly or indirectly by the object, are serializable. (In other words, they must implement java.io.Serializable.) Fortunately it is often sufficient to simply declare that a given class implements java.io.Serializable and let Java’s default serialization mechanisms do their thing. Java Object Serialization is slow, and using it to make a deep copy requires both serializing and deserializing.
There are ways to speed it up (e.g., by pre-computing serial version ids and defining custom readObject() and writeObject() methods), but this will usually be the primary bottleneck. The byte array stream implementations included in the java.io package are designed to be general enough to perform reasonable well for data of different sizes and to be safe to use in a multi-threaded environment. These characteristics, however, slow down ByteArrayOutputStream and (to a lesser extent) ByteArrayInputStream .

Q4) What is difference between deep and shallow cloning?

Ans) The differences are as follows:

Consider the class:
public class MyData{
String id;
Map myData;
}

The shallow copying of this object will have new id object and values as “” but will point to the myData of the original object. So a change in myData by either original or cloned object will be reflected in other also. But in deep copying there will be new id object and also new myData object and independent of original object but with same values.

Shallow copying is default cloning in Java which can be achieved using clone() method of Object class. For deep copying some extra logic need to be provided.

Q5) What are the characteristics of a shallow clone?

Ans) If we do a = clone(b)
1) Then b.equals(a)
2) No method of a can modify the value of b.

Q6) What are the disadvantages of deep cloning?

Ans) Disadvantages of using Serialization to achieve deep cloning –

Serialization is more expensive than using object.clone().
Not all objects are serializable.
Serialization is not simple to implement for deep cloned object..

What is a java marker interface?

Java marker interface has no members in it. Marker interface ‘was’ used as a tag to inform a message to the java compiler.

Java Marker Interface Examples:
java.lang.Cloneable
java.io.Serializable
java.util.EventListener

Lets take the java.io.Serializable marker interface. It doesnot has any members defined it it. When a java class is to be serialized, you should intimate the java compiler in some way that there is a possibility of serializing this java class. In this scenario, marker interfaces are used. The java class which may be serialized has to implement the java.io.Serializable marker interface. In such way, we are intimating the java compiler.

From java 1.5, the need for marker interface is eliminated by the introduction of the java annotation feature. So, it is wise to use java annotations than the marker interface. It has more feature and advantages than the java marker interface.


Java Clone, Shallow Copy and Deep Copy

Java provides a mechanism for creating copies of objects called cloning. There are two ways to make a copy of an object called shallow copy and deep copy. See here to understand that.
Java Clone
Java supports shallow and deep copy with the Cloneable interface to create copies of objects. To make a clone of a Java object, you declare that an object implements Cloneable, and then provide an override of the clone method of the standard Java Object base class. Implementing Cloneable tells the java compiler that your object is Cloneable. The cloning is actually done by the clone method.

In java, though clone is ‘intended’ to produce a copy of the same object, though it is not guaranteed. Clone comes with lots of ifs and buts. So my first advice is to not depend on clones. If you want to provide a handle / method to deliver a copy of the current instance write a kind of factory method and provide it with a good documentation. When you are in a situation to use a third party component and produce copies of it using the clone method, then investigate that implementation carefully and get to know what is underlying.

Supporting Shallow Copy by clone

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.

Note that for primitive types, shallow copy works fine, but for classes having other class or user defined types, it may be a problem. So if there is no problem with shallow copies, its fine, otherwise we need deep copies.

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 a 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.

Example - Shallow and Deep Copy :

import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;

public class CloningExample implements Cloneable {

private LinkedList names = new LinkedList();
public CloningExample() {
names.add(“Alex”);
names.add(“Melody”);
names.add(“Jeff”);
}
public String toString() {
StringBuffer sb = new StringBuffer();
Iterator i = names.iterator();
while (i.hasNext()) {
sb.append(“\n\t” + i.next());
}
return sb.toString();
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new Error(“This should not occur since we implement Cloneable”);
}
}
public Object deepClone() {
try {
CloningExample copy = (CloningExample)super.clone();
copy.names = (LinkedList)names.clone();
return copy;
} catch (CloneNotSupportedException e) {
throw new Error(“This should not occur since we implement Cloneable”);
}
}

public boolean equals(Object obj) {

/* is obj reference this object being compared */
if (obj == this) {
return true;
}

/* is obj reference null */
if (obj == null) {
return false;
}

/* Make sure references are of same type */
if (!(this.getClass() == obj.getClass())) {
return false;
} else {
CloningExample tmp = (CloningExample)obj;
if (this.names == tmp.names) {
return true;
} else {
return false;
}
}

}


public static void main(String[] args) {

CloningExample ce1 = new CloningExample();
System.out.println(“\nCloningExample[1]\n” +
“—————–” + ce1);

CloningExample ce2 = (CloningExample)ce1.clone();
System.out.println(“\nCloningExample[2]\n” +
“—————–” + ce2);

System.out.println(“\nCompare Shallow Copy\n” +
“——————–\n” +
“ ce1 == ce2 :+ (ce1 == ce2) + “\n” +
“ ce1.equals(ce2) :+ ce1.equals(ce2));

CloningExample ce3 = (CloningExample)ce1.deepClone();
System.out.println(“\nCompare Deep Copy\n” +
“——————–\n” +
“ ce1 == ce3 :+ (ce1 == ce3) + “\n” +
“ ce1.equals(ce3) :+ ce1.equals(ce3));

System.out.println();

}

}

So as we see in deepClone, lists are explicitly copied.
In this case the shallow copy has the same reference ( == ) and the deep copy only has an equivalent reference ( .equals() ).