Object Cloning in Java
A clone is an exact copy of the original. In java, it essentially means the ability to create an object with similar state as the original object. The clone() method provides this functionality.
The java.lang.Cloneable interface must be implemented by the class whose clone object wants to create. If Cloneable interface is not implemented, clone() method generates CloneNotSupportedException.
protected Object clone() throws CloneNotSupportedException
Facts about cloning
By default, java cloning is ‘field by field copy’ i.e. as the Object class does not have idea about the structure of class on which clone() method will be invoked. So, JVM when called for cloning, do following things:
1) 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.
2) 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.
Facts behind cloning
1) You must implement Cloneable interface.
2) You must override clone() method from Object class. [Its weird. clone() method should have been in Cloneable interface.]
/*
Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object.
The general intent is that, for any object x, the expression:
1) x.clone() != x will be true
2) x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.
3) x.clone().equals(x) will be true, this is not an absolute requirement.
*/
protected native Object [More ...] clone() throws CloneNotSupportedException;
1. First statement guarantees that cloned object will have separate memory address assignment.
2. Second statement suggests that original and cloned objects should have same class type, but it is not mandatory.
3. Third statement suggests that original and cloned objects should have be equal using equals() method, but it is not mandatory.
public class Employee implements Cloneable {
private int empoyeeId;
private String employeeName;
private Department department;
public Employee(int id, String name, Department dept) {
this.empoyeeId = id;
this.employeeName = name;
this.department = dept;
}
/** Shallow copy. */
/*@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}*/
/** Deep copy. */
@Override
protected Object clone() throws CloneNotSupportedException {
Employee cloned = (Employee)super.clone();
cloned.setDepartment((Department)cloned.getDepartment().clone());
return cloned;
}
/** setters and getters. */
}
public class Department {
private int id;
private String name;
public Department(int id, String name) {
this.setId(id);
this.setName(name);
}
/** for deep copy. */
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
/** setters and getters. */
}
public class TestCloning {
public static void main(String[] args) throws CloneNotSupportedException {
Department dept = new Department(1, "Human Resource");
Employee original = new Employee(1, "Admin", dept);
//Lets create a clone of original object
Employee cloned = (Employee) original.clone();
//Let verify using employee id, if cloning actually workded
System.out.println(cloned.getEmpoyeeId());
//Must be true and objects must have different memory addresses
System.out.println(original != cloned);
//As we are returning same class; so it should be true
System.out.println(original.getClass() == cloned.getClass());
//Default equals method checks for refernces so it should be false.
If we want to make it true.
//we need to override equals method in Employee class.
System.out.println(original.equals(cloned));
}
}
protected native Object clone() throws CloneNotSupportedException;
ReplyDeleteprotected method of Object class.
So it mandatory to Override it.
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
CloneTest obj = new CloneTest();
CloneTest clonedObj = (CloneTest) obj.clone();
if(obj==clonedObj) {
System.out.println("equal");
} else {
System.out.println("cloned new instanse");
}
}
}
Exception:
Exception in thread "main" java.lang.CloneNotSupportedException: com.clone.CloneTest
at java.lang.Object.clone(Native Method)
at com.clone.CloneTest.main(CloneTest.java:6)
If Clonable interface is implemented without clone() method Overriding,
DeleteThere will be deafault cloning with Shallow copy.
public class CloneTest implements Cloneable {
public static void main(String[] args) throws CloneNotSupportedException {
CloneTest obj = new CloneTest();
CloneTest clonedObj = (CloneTest) obj.clone();
if(obj==clonedObj) {
System.out.println("equal");
} else {
System.out.println("cloned new instanse");
}
}
}
cloned new instanse
If you want to perform cloning, it is must to implement the Cloneable interface.
Deleteclone() method overriding needed when you want to perform Deep copy !!
If the Clonable (Marker interface) interface is not implemented, there will be an exception. because JVM will unable to understand that its an clonable object !
ReplyDeletepublic class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
CloneTest obj = new CloneTest();
CloneTest clonedObj = (CloneTest) obj.clone();
if(obj==clonedObj) {
System.out.println("equal");
} else {
System.out.println("cloned new instanse");
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Exception in thread "main" java.lang.CloneNotSupportedException: com.clone.CloneTest
at java.lang.Object.clone(Native Method)
at com.clone.CloneTest.clone(CloneTest.java:18)
at com.clone.CloneTest.main(CloneTest.java:6)
public class CloneTest implements Cloneable {
Deletepublic static void main(String[] args) throws CloneNotSupportedException {
CloneTest obj = new CloneTest();
CloneTest clonedObj = (CloneTest) obj.clone();
if(obj==clonedObj) {
System.out.println("equal");
} else {
System.out.println("cloned new instanse");
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Output :
loned new instanse