Friday, June 13, 2008

What is Cloning? How clone() method works in Java?


What is the role of the clone() method in Java?

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 Next - Deep Copy vs Shallow Copy >> You may browse the links given in that article to go through various aspects of Cloning in Java). This can be understood easily by looking at the following memory diagram:-



Liked the article? You may like to Subscribe to this blog for regular updates. You may also like to follow the blog to manage the bookmark easily and to tell the world that you enjoy GeekExplains. You can find the 'Followers' widget in the rightmost sidebar.



Share/Save/Bookmark


10 comments:

groupon clone said...

Nice updates!! I like your information so much...

Anonymous said...

Clearly explained. Thanks.
But I am not clear how it returns
objA.equals(objACloned) --> true, initially even.

When clone objeA and create ObjACloned, it creates separate memory location for cloned obj.


A objA = new A();
A objACloned = (A) objA.clone();

Geek said...

Not sure if I understood your question.

Result of objA.equals(objACloned) obviously depends upon how have you overridden 'equals' for Class A. But, assuming your 'equals' implementation is checking the values of members, then objA.equals(objACloned) will initially return 'true' as shallow copy (default clone impl) will get new copies of primitives while the object references will continue to remain same so unless you change something in the primitives, objjA.equals(objACloned) will continue to get you 'true'.

Sounds better now? Let me know if your question was different.

Anonymous said...

Nice explaination. I have one doubt though. What if i change the member object variable value as in below? it should reflect the new changed values in original object, right?

public class CloneExample
{
public static void main(String arg[])
{
Employee jwz = new Employee();
jwz.setName("XYZ");
jwz.setDesignation("CA");

try
{
Employee joel = (Employee) jwz.clone();
System.out.println(joel.getName()); //prints XYZ
System.out.println(joel.getDesignation()); //prints CA

jwz.setName("PQR");
jwz.setDesignation("Teacher");

System.out.println(joel.getName());
System.out.println(joel.getDesignation());
}
catch (CloneNotSupportedException cnse)
{
System.out.println("Cloneable should be implemented. " + cnse);
}
}
}


but its not happening. Can you explain a bit more?

Geek said...

"PQR" basically creates a 'new' String object and when you call jwz.setName("PQR") then the object reference of 'name' field in 'jwz' instance gets reset with the newly created reference for "PQR" (assuming usual 'Employee' class/method definition). Does this help?

Please publish more details as to what you observe and what exactly you expect... I might be able to explain it better then.

Yashu said...

Thanks for such a nice explanation on object copying

Richard Byrdk said...
This comment has been removed by the author.
Shwetha said...

Simple and easy to understand. Helps in understanding the problem associated with clone. Thank you.

Anonymous said...

Simple and clear explanation. Thank you.

Anonymous said...

I had lots of doubt about object cloning and clone method, and this post certainly helps me. It's tricky and not definitely not easy.