Clone
1. What is java exactly do in
assignment operator?
In Java, when you assign an object to another
variable, only the memory address of the object is copied and hence any changes
in the original object will be reflected in the new variable.
Object obj1=new Object ();
Object obj2 =null;
obj2 = obj1;
Here, in this case any changes you make to obj1 will reflect in
obj2 and vice versa. Well, if this is what you want, then no issues but if you
don’t want the change made in obj2 to be seen in obj1 or any change made in
obj1 to be seen in obj2, then cloning comes into picture.
2. So why need Clone?
Well, cloning means creating a copy of the
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:
·
x.clone(); // will be true, and that the expression:
·
x.clone().getClass()
==x.getClass() // will be true, but
these are not absolute requirements. While it is typically the case that
·
x.clone().equals(x);//
will be true, and
this is also not an absolute requirement.
3. Type of Clone
3.1. Shallow clone
3.2. Deep clone
4. What is shallow clone
This is default implementation in java. In overridden clone method, if you are not cloning all
the object types (not primitives), then you are making a shallow copy.
Example:
package com.clone;
public class
Department
{
private int id;
private String name;
public Department(int id,
String name)
{
this.id = id;
this.name = name;
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int
id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void
setName(String name) {
this.name = name;
}
}
|
package com.clone;
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;
}
@Override
protected
Object clone() throws CloneNotSupportedException {
return
super.clone();
}
/**
* @return the empoyeeId
*/
public int
getEmpoyeeId() {
return empoyeeId;
}
/**
* @param empoyeeId the empoyeeId to
set
*/
public void
setEmpoyeeId(int empoyeeId) {
this.empoyeeId =
empoyeeId;
}
/**
* @return the employeeName
*/
public String getEmployeeName()
{
return employeeName;
}
/**
* @param employeeName the
employeeName to set
*/
public void
setEmployeeName(String employeeName) {
this.employeeName =
employeeName;
}
/**
* @return the department
*/
public Department
getDepartment() {
return department;
}
/**
* @param department the department to
set
*/
public void
setDepartment(Department department) {
this.department =
department;
}
}
|
package com.clone;
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);
// Employee original = new Employee(1, "Admin");
//Lets create a clone of original object
System.out.println(original);
Employee cloned =
(Employee) original.clone();
System.out.println(cloned);
//Let verify using employee id, if cloning actually workded
/*System.out.println(cloned.getEmpoyeeId());
//Verify JDK's rules
//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));*/
//Shallow clone example where department not done any clone so it will
done as same Behavior of object assignment
//but in Employee class is done cloning so only it will effect in
employee class object
cloned.getDepartment().setName("Finance");
original.getDepartment().setName("Software");
System.out.println(original.getDepartment().getName());
System.out.println(cloned.getDepartment().getName());
//System.out.println(original.getEmployeeName());
//This is Employee class clone data changes
cloned.setEmployeeName("ABC");
System.out.println(original.getEmployeeName());
System.out.println(cloned.getEmployeeName());
original.setEmployeeName("DDD");
System.out.println(original.getEmployeeName());
System.out.println(cloned.getEmployeeName());
}
}
|
OutPut:
com.clone.Employee@447d4275
com.clone.Employee@7b963273
Software
Software
Admin
ABC
DDD
ABC
|
5. Deep clone
5.1. We
want a clone which is independent of original and making changes in clone
should not affect original.
5.2. Example
of Deep clone
package com.clon;
public class
Department implements Cloneable
{
private int id;
private String name;
public Department(int id,
String name)
{
this.id = id;
this.name = name;
}
@Override
protected Object clone() throws
CloneNotSupportedException {
return
super.clone();
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int
id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void
setName(String name) {
this.name = name;
}
}
|
package com.clon;
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;
}
@Override
protected
Object clone() throws CloneNotSupportedException {
Employee
cloned = (Employee)super.clone();
cloned.setDepartment((Department)cloned.getDepartment().clone());
return
cloned;
}
/**
* @return the empoyeeId
*/
public int
getEmpoyeeId() {
return empoyeeId;
}
/**
* @param empoyeeId the empoyeeId to
set
*/
public void
setEmpoyeeId(int empoyeeId) {
this.empoyeeId =
empoyeeId;
}
/**
* @return the employeeName
*/
public String getEmployeeName()
{
return employeeName;
}
/**
* @param employeeName the
employeeName to set
*/
public void
setEmployeeName(String employeeName) {
this.employeeName =
employeeName;
}
/**
* @return the department
*/
public Department
getDepartment() {
return department;
}
/**
* @param department the department to
set
*/
public void
setDepartment(Department department) {
this.department =
department;
}
}
|
package com.clon;
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);
// Employee original = new Employee(1, "Admin");
//Lets create a clone of original object
System.out.println(original);
Employee cloned =
(Employee) original.clone();
System.out.println(cloned);
//Let verify using employee id, if cloning actually workded
/* System.out.println(cloned.getEmpoyeeId());
//Verify JDK's rules
//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));*/
//this is for hole class need to clone
System.out.println(original.getDepartment().getName());
cloned.getDepartment().setName("Finance");
original.getDepartment().setName("Software");
System.out.println(original.getDepartment().getName());
System.out.println(cloned.getDepartment().getName());
cloned.setEmployeeName("ABC");
System.out.println(original.getEmployeeName());
System.out.println(cloned.getEmployeeName());
original.setEmployeeName("DDD");
System.out.println(original.getEmployeeName());
System.out.println(cloned.getEmployeeName());
}
}
|
Output:
com.clon.Employee@16721ee7
com.clon.Employee@1e4adb34
Human Resource
Software
Finance
Admin
ABC
DDD
ABC
|