• In Java Cloning is a process to create a clone or copy of an existing object.
• After Cloning we get a different object, this means the reference of the cloned objects will be different from the original or existing object but the value of the class level variables and all the functionalities will be the same as original or existing object.
class JTC{
public static void main(String arg[]){
Student s1 = new Student(101,"Vivek","Noida");
Student copy = new Student(101,"Vivek","Noida");
// We are creating the clone or copy of the s1
Student clone = new Student(s1.sid,s1.sname,s1.scity);
System.out.println("s1.hashCode :- "+s1.hashCode());
System.out.println("clone.hashCode :- "+clone.hashCode());
System.out.println(s1.equals(clone));
s1.show();
copy.show();
}
}
class Student{
int sid;
String sname;
String scity;
{
System.out.println("Instance block of Student class");
}
Student(int sid, String sname, String scity){
System.out.println("Constructor of Student class");
this.sid = sid;
this.sname = sname;
this.scity = scity;
}
void show(){
System.out.println("---Student Details---");
System.out.println("sid :- "+sid);
System.out.println("sname :- "+sname);
System.out.println("scity :- "+scity);
}
}
Instance block of Student class Constructor of Student class Instance block of Student class Constructor of Student class Instance block of Student class Constructor of Student class s1.hashCode :- 306123060 clone.hashCode :- 2104028992 false ---Student Details--- sid :- 101 sname :- Vivek scity :- Noida ---Student Details--- sid :- 101 sname :- Vivek scity :- Noida
In the above example we can see that we have a Student class. In the Student class we have certain members which are three instance variables- int sid, String sname, String scity; there is an Instance Block; a parameterized constructor which is injecting the data into the instance variables; and an instance method void show() that has an implementation code for printing the details of a student.
In JTC class we can see that first we are creating an object of Student class along with students’ details and in the next line we are creating a new object of Student class which seems like a copy of the existing object of Student class because Student details are same as first object s1.
In this example we are creating Student class object clone manually, it means we are not using any built-in method. In this manner we will get constructor invocation or instance block invocation of clone object as well, this will increase the response time of the application.
• In Java we have clone() method in java.lang.Object class to create the clone of an existing object.
Access Modifier: - protected
Types of Member: - Instance Method
Return Type: - java.lang.Object
Method Name: - clone()
Functionality: - When we invoke clone() of java.lang.Object class along with an object then it returns the copy of the current working object and internally it reduces the execution time as well, this is because in clone method constructor and instance block do not execute for clone objects and hence execution time is saved. An important point which we must remember is that the current working object class of clone() has to implement java.lang.Clonable interface which is a Marker Interface, otherwise at the time of execution we get a checked exception which is java.lang.CloneNotSupportedException.
class Student implements Cloneable{
int sid;
String sname;
String scity;
{
System.out.println("Instance block of Student class");
}
Student(int sid, String sname, String scity){
System.out.println("Constructor of Student class");
this.sid = sid;
this.sname = sname;
this.scity = scity;
}
void show(){
System.out.println("---Student Details---");
System.out.println("sid :- "+sid);
System.out.println("sname :- "+sname);
System.out.println("scity :- "+scity);
}
public static void main(String arg[]) throws CloneNotSupportedException{
Student s1 = new Student(101,"Vivek","Noida");
// We are creating the clone or copy of the s1 object using clone()
Student clone = (Student)s1.clone();
System.out.println("s1.hashCode :- "+s1.hashCode());
System.out.println("clone.hashCode :- "+clone.hashCode());
System.out.println(s1.equals(clone));
s1.show();
clone.show();
}
}
Instance block of Student class Constructor of Student class s1.hashCode :- 680576081 clone.hashCode :- 1088872417 false ---Student Details--- sid :- 101 sname :- Vivek scity :- Noida ---Student Details--- sid :- 101 sname :- Vivek scity :- Noida
In the above example we have Student class and it is implementing java.lang. Cloneable interface because in further code we are invoking clone() of java.lang.Object class along with Student class object s1. In the output we can see that we have successfully created a copy of s1 object. The most important point which we should note in the output is that the instance block and constructor of Student class does not process for the clone object.
• Types of Cloning: -
1. Shallow Cloning
2. Deep Level Cloning
When any memory problem is detected by JVM inside the Heap Area than JVM follows the below mentioned steps: -
• In Shallow Cloning we can create the copy of the Top-Level Object only. This means we can create the clone of the current working object (Top Level Object) of clone() method only and not of all those objects on which current working object or top level object is dependent.
• The default implementation of java.lang.Object class clone() method is dedicated to perform Shallow Cloning.
class JTC{
public static void main(String arg[]) throws CloneNotSupportedException{
A a1 = new A(101);
B b1 = new B(202,a1);
C c1 = new C(303,b1);
C clone = c1.getClone();
System.out.println("----c1 details----");
System.out.println("c1.hashCode :- "+c1.hashCode());
System.out.println("c1.b1.hashCode :- "+c1.b1.hashCode());
System.out.println("c1.b1.a1.hashCode :- "+c1.b1.a1.hashCode());
System.out.println("c1.c :- "+c1.c);
System.out.println("c1.b1.b :- "+c1.b1.b);
System.out.println("c1.b1.a1.a :- "+c1.b1.a1.a);
System.out.println("\n----clone details----");
System.out.println("clone.hashCode :- "+clone.hashCode());
System.out.println("clone.b1.hashCode :- "+clone.b1.hashCode());
System.out.println("clone.b1.a1.hashCode :- "+clone.b1.a1.hashCode());
System.out.println("clone.c :- "+clone.c);
System.out.println("clone.b1.b :- "+clone.b1.b);
System.out.println("clone.b1.a1.a :- "+clone.b1.a1.a);
System.out.println("c1.eqauls(clone) :- "+c1.equals(clone));
System.out.println("c1.b1.eqauls(clone.b1) :- "+c1.b1.equals(clone.b1));
System.out.println("c1.b1.a1.eqauls(clone.b1.a1) :- "+c1.b1.a1.equals(clone.b1.a1));
}
}
class A{
int a;
A(int a){
this.a = a;
}
}
class B{
int b;
A a1;
B(int b, A a1){
this.b = b;
this.a1 = a1;
}
}
class C implements Cloneable{
int c;
B b1;
C(int c, B b1){
this.c = c;
this.b1 = b1;
}
C getClone() throws CloneNotSupportedException{
return (C) this.clone();
}
}
----c1 details---- c1.hashCode :- 2041416495 c1.b1.hashCode :- 502800944 c1.b1.a1.hashCode :- 576936864 c1.c :- 303 c1.b1.b :- 202 c1.b1.a1.a :- 101 ----clone details---- clone.hashCode :- 331418503 clone.b1.hashCode :- 502800944 clone.b1.a1.hashCode :- 576936864 clone.c :- 303 clone.b1.b :- 202 clone.b1.a1.a :- 101 c1.eqauls(clone) :- false c1.b1.eqauls(clone.b1) :- true c1.b1.a1.eqauls(clone.b1.a1) :- true
In the above example we have four classes class A, class B, class C and class JTC. As you can see that class B is dependent on class A and class C is dependent on class B. This means that in order to create an object of B class we have to create an object of A class first and pass as an argument into the B class constructor, and same process will be applicable in the case of class C which is dependent on class B.
In JTC class we are invoking getClone() along with c1 and getClone() method is internally invoking clone(), so indirectly the current working object or top level object is c1 here . For c1 deep level, the objects are b1 and a1 because c1 is directly dependent on b1 and indirectly dependent on a1.
In the last section, in the output of the above example where we are printing the details of c1 and clone we can see that c1.b1.hashCode and clone.b1.hashCode are same. Similarly c1.b1.a1.hashCode and clone.b1.a1.hashCode are same, as well as the outputs for c1.b1.equals(clone.b1) and c1.b1.a1.equals(clone.b1.a1) are true. This proves that clone() method of java.lang.Object class performs Shallow Cloning.
• In Deep level Cloning we get the copy of Top-Level Object as well as copy of the Deep Level Objects.
• As we know the default implementation of the clone() method in java.lang.Object class is dedicated to Shallow Cloning, so in order to achieve the Deep Level Cloning in the program we have to override the clone() into the sub class.
class JTC{
public static void main(String arg[]) throws CloneNotSupportedException{
A a1 = new A(101);
B b1 = new B(202,a1);
C c1 = new C(303,b1);
C clone = c1.getClone();
System.out.println("----c1 details----");
System.out.println("c1.hashCode :- "+c1.hashCode());
System.out.println("c1.b1.hashCode :- "+c1.b1.hashCode());
System.out.println("c1.b1.a1.hashCode :- "+c1.b1.a1.hashCode());
System.out.println("c1.c :- "+c1.c);
System.out.println("c1.b1.b :- "+c1.b1.b);
System.out.println("c1.b1.a1.a :- "+c1.b1.a1.a);
System.out.println("\n----clone details----");
System.out.println("clone.hashCode :- "+clone.hashCode());
System.out.println("clone.b1.hashCode :- "+clone.b1.hashCode());
System.out.println("clone.b1.a1.hashCode :- "+clone.b1.a1.hashCode());
System.out.println("clone.c :- "+clone.c);
System.out.println("clone.b1.b :- "+clone.b1.b);
System.out.println("clone.b1.a1.a :- "+clone.b1.a1.a);
System.out.println("c1.eqauls(clone) :- "+c1.equals(clone));
System.out.println("c1.b1.eqauls(clone.b1) :- "+c1.b1.equals(clone.b1));
System.out.println("c1.b1.a1.eqauls(clone.b1.a1) :- "+c1.b1.a1.equals(clone.b1.a1));
}
}
class A{
int a;
A(int a){
this.a = a;
}
}
class B{
int b;
A a1;
B(int b, A a1){
this.b = b;
this.a1 = a1;
}
}
class C implements Cloneable{
int c;
B b1;
C(int c, B b1){
this.c = c;
this.b1 = b1;
}
// Overrideing the clone() method
protected Object clone() throws CloneNotSupportedException{
// getting the information of all the interfaces which are implementd by C class
Class ar1[] = this.getClass().getInterfaces();
C c_clone = null;
// Checking C class implementing Cloneable interface or not.
if(ar1[0].getName().equals("java.lang.Cloneable")){
A a_clone = new A(this.b1.a1.a);
B b_clone = new B(this.b1.b,a_clone);
c_clone = new C(this.c,b_clone);
}else{
// If C class does not implement Cloneable interface than it throws Exception.
throw new CloneNotSupportedException();
}
return c_clone;
}
C getClone() throws CloneNotSupportedException{
return (C) this.clone();
}
}
----c1 details---- c1.hashCode :- 2085002312 c1.b1.hashCode :- 317071334 c1.b1.a1.hashCode :- 2129221032 c1.c :- 303 c1.b1.b :- 202 c1.b1.a1.a :- 101 ----clone details---- clone.hashCode :- 1472465 clone.b1.hashCode :- 1224347463 clone.b1.a1.hashCode :- 1791045777 clone.c :- 303 clone.b1.b :- 202 clone.b1.a1.a :- 101 c1.eqauls(clone) :- false c1.b1.eqauls(clone.b1) :- false c1.b1.a1.eqauls(clone.b1.a1) :- false
In the above example we have four classes- class A, class B, class C and class JTC and as you can see class B is dependent on class A and class C is dependent on class B; this means that in order to create an object of B class we have to create an object of A class first and pass as an argument into the B class constructor and the same process is applicable in the case of class C which is dependent on class B.
In C class as we can see that we are overriding clone() to implement Deep Level Cloning.
In JTC class we are invoking getClone() along with c1 and getClone() method is internally invoking clone(), so indirectly the current working object or top level object is c1 here. For c1 deep level the objects are b1 and a1 because c1 is directly dependent on b1 and indirectly dependent on a1.
In the last section in the output of the above example where we are printing the details of c1 and clone; we can see c1.b1.hashCode and clone.b1.hashCode are different, unlike Shallow Cloning example. Similarly c1.b1.a1.hashCode and clone.b1.a1.hashCode are different ; c1.b1.equals(clone.b1) is false, c1.b1.a1.equals(clone.b1.a1) is false. This output proves that using clone() method in this example we have successfully achieved Deep Level Cloning, this means we are able to get the copy of C class object c1 as well as their Deep Level Objects.