Object cloning refers to creation of exact copy of an object. It creates a new instance of the class of current object and initializes all its fields with exactly the contents of the corresponding fields of this object.
Using Assignment Operator to create copy of reference variable
In Java, there is no operator to create copy of an object. Unlike C++, in Java, if we use assignment operator then it will create a copy of reference variable and not the object. This can be explained by taking an example. Following program demonstrates the same.
packagecom.gs.corejava.collections;//Java program to demonstrate that assignment //operator only creates a new reference to same //object. //A test class whose objects are cloned classTest {int x, y;Test() { x =10; y =20; }}// Driver ClasspublicclassMain {publicstaticvoidmain(String[] args) {Test ob1 =newTest();System.out.println(ob1.x+" "+ob1.y);// Creating a new reference variable ob2// pointing to same address as ob1Test ob2 = ob1;// Any change made in ob2 will be reflected// in ob1ob2.x=100;System.out.println(ob1.x+" "+ob1.y);System.out.println(ob2.x+" "+ob2.y); }}
Output:
10 20
100 20
100 20
Creating a copy using clone() method
The class whose object’s copy is to be made must have a public clone method in it or in one of its parent class.
Every class that implements clone() should call super.clone() to obtain the cloned object reference.
The class must also implement java.lang.Cloneable interface whose object clone we want to create otherwise it will throw CloneNotSupportedException when clone method is called on that class’s object.
packagecom.gs.corejava.collections;//Java program to demonstrate that assignment //operator only creates a new reference to same //object. //A test class whose objects are cloned classTestimplementsCloneable {int x, y;Test() { x =10; y =20; } @OverrideprotectedObjectclone() throwsCloneNotSupportedException {return super.clone(); }}// Driver ClasspublicclassMain {publicstaticvoidmain(String[] args) {Test ob1 =newTest();System.out.println(ob1.x+" "+ob1.y);// Creating a new reference variable ob2// pointing to same address as ob1Test ob2 =null;try { ob2 = (Test) ob1.clone(); } catch (CloneNotSupportedException e) {// TODO Auto-generated catch blocke.printStackTrace(); }// Any change made in ob2 will be reflected// in ob1ob2.x=100;System.out.println(ob1.x+" "+ob1.y);System.out.println(ob2.x+" "+ob2.y); }}
Output:
10 20
10 20
100 20
Usage of clone() method -Shallow Copy
packagecom.gs.corejava.collections;//A Java program to demonstrate shallow copy //using clone() //An object reference of this class is //contained by Test2 classTest {int x, y;}// Contains a reference of Test and implements// clone with shallow copy.classTest2implementsCloneable {int a;int b;Test c =newTest();publicObjectclone() throwsCloneNotSupportedException {return super.clone(); }}// Driver classpublicclassMain {publicstaticvoidmain(String args[]) throwsCloneNotSupportedException {Test2 t1 =newTest2();t1.a=10;t1.b=20;t1.c.x=30;t1.c.y=40;// Creating a copy of object t1 and passing it to t2Test2 t2 = (Test2) t1.clone(); // Change in primitive type of t2 will not be reflected in t1 fieldt2.a=100;// Change in object type field will be reflected in both t2 and t1(shallow copy)t2.c.x=300;System.out.println(t1.a+" "+t1.b+" "+t1.c.x+" "+t1.c.y);System.out.println(t2.a+" "+t2.b+" "+t2.c.x+" "+t2.c.y); }}
Output:
10 20 300 40
100 20 300 40
In the above example, t1.clone returns the shallow copy of the object t1. To obtain a deep copy of the object certain modifications have to be made in clone method after obtaining the copy.
Deep Copy vs Shallow Copy
Shallow copy is method of copying an object and is followed by default in cloning. In this method the fields of an old object X are copied to the new object Y. While copying the object type field the reference is copied to Y i.e object Y will point to same location as pointed out by X. If the field value is a primitive type it copies the value of the primitive type.
Therefore, any changes made in referenced objects in object X or Y will be reflected in other object.
Shallow copies are cheap and simple to make. In above example, we created a shallow copy of object.
Usage of clone() method – Deep Copy
If we want to create a deep copy of object X and place it in a new object Y then new copy of any referenced objects fields are created and these references are placed in object Y. This means any changes made in referenced object fields in object X or Y will be reflected only in that object and not in the other. In below example, we create a deep copy of object.
A deep copy copies all fields, and makes copies of dynamically allocated memory pointed to by the fields. A deep copy occurs when an object is copied along with the objects to which it refers.
packagecom.gs.corejava.collections;//A Java program to demonstrate deep copy //using clone() //An object reference of this class is //contained by Test2 classTest {int x, y;}// Contains a reference of Test and implements// clone with deep copy.classTest2implementsCloneable {int a, b;Test c =newTest();publicObjectclone() throwsCloneNotSupportedException {// Assign the shallow copy to new refernce variable tTest2 t = (Test2) super.clone();// Create a new object for the field c// and assign it to shallow copy obtained,// to make it a deep copyt.c=newTest();return t; }}publicclassMain {publicstaticvoidmain(String args[]) throwsCloneNotSupportedException {Test2 t1 =newTest2();t1.a=10;t1.b=20;t1.c.x=30;t1.c.y=40;Test2 t3 = (Test2) t1.clone();// Change in primitive type of t2 will not// be reflected in t1 fieldt3.a=100;// Change in object type field of t2 will not// be reflected in t1(deep copy)t3.c.x=300;System.out.println(t1.a+" "+t1.b+" "+t1.c.x+" "+t1.c.y);System.out.println(t3.a+" "+t3.b+" "+t3.c.x+" "+t3.c.y); }}
Output:
10 20 30 40
100 20 300 0
Cloning with inheritance (Shallow) :
Example 1:
packagecom.gs.corejava.collections;//: appendixa:HorrorFlick.java//You can insert Cloneability at any level of inheritance.//From 'Thinking in Java, 3rd ed.' (c) Bruce Eckel 2002//www.BruceEckel.com. See copyright notice in CopyRight.txt.classPerson {}classHeroextendsPerson {}classScientistextendsPersonimplementsCloneable {publicObjectclone() {try {return super.clone(); } catch (CloneNotSupportedException e) {// This should never happen: It's Cloneable already!thrownewRuntimeException(e); } }}classMadScientistextendsScientist {}publicclassHorrorFlick {publicstaticvoidmain(String[] args) {Person p =newPerson();Hero h =newHero();Scientist s =newScientist();MadScientist m =newMadScientist();// ! p = (Person)p.clone(); // Compile error// ! h = (Hero)h.clone(); // Compile error s = (Scientist) s.clone();System.out.println(m.clone().getClass()); m = (MadScientist) m.clone(); }} // /:~
Example 2:
packagecom.gs.corejava.collections;classAimplementsCloneable { @OverrideprotectedAclone() throwsCloneNotSupportedException// could be public {Object clone = super.clone();System.out.println("Class A: "+clone.getClass()); // will print 'C'return (A) clone; }}classBextendsA { @OverrideprotectedBclone() throwsCloneNotSupportedException {A clone = super.clone();System.out.println("Class B: "+clone.getClass()); // will print 'C'return (B) clone; }}classCextendsB { @OverrideprotectedCclone() throwsCloneNotSupportedException {B clone = super.clone();System.out.println("Class C: "+clone.getClass()); // will print 'C'return (C) clone; }}publicclassTestI {publicstaticvoidmain(String argv[]) {C c =newC();try {A cloned_c =c.clone(); } catch (CloneNotSupportedException e) {// TODO Auto-generated catch blocke.printStackTrace(); } }}
Output:
Class A: class com.gs.corejava.collections.C
Class B: class com.gs.corejava.collections.C
Class C: class com.gs.corejava.collections.C