克隆是完全复制另一个物体,在java中,意味着创建一个和原对象有相似状态的对象。clone()方法就提供了这个功能,在这篇文章中,我们将探索java 克隆的一些最重要的方面。这篇文章是mini guides的一个部分
/* 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 clone() throws CloneNotSupportedException;
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(); } //Accessor/mutators methods will go there }
public class Department { private int id; private String name; public Department(int id, String name) { this.id = id; this.name = name; } //Accessor/mutators methods will go there }
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()); //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)); } } Output: 1 true true false
public class TestCloning { public static void main(String[] args) throws CloneNotSupportedException { Department hr = new Department(1, "Human Resource"); Employee original = new Employee(1, "Admin", hr); Employee cloned = (Employee) original.clone(); //Let change the department name in cloned object and we will verify in original object cloned.getDepartment().setName("Finance"); System.out.println(original.getDepartment().getName()); } } Output: Finance
//Modified clone() method in Employee class @Override protected Object clone() throws CloneNotSupportedException { Employee cloned = (Employee)super.clone(); cloned.setDepartment((Department)cloned.getDepartment().clone()); return cloned; }
//Defined clone method in Department class. @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }
public class TestCloning { public static void main(String[] args) throws CloneNotSupportedException { Department hr = new Department(1, "Human Resource"); Employee original = new Employee(1, "Admin", hr); Employee cloned = (Employee) original.clone(); //Let change the department name in cloned object and we will verify in original object cloned.getDepartment().setName("Finance"); System.out.println(original.getDepartment().getName()); } } Output: Human Resource
那么深克隆需要满足下边的情况:
1、没有必要单独复制primitive
2、原生对象中的所有类成员都必须支持clone方法,在原生对象的成员类中都要调用super.clone()方法
3、如果类成员变量不支持clone,那么它必须创建那个成员类的新的实例,并把它的属性一个一个的复制到新的对象中去,新的类成员对象在clone对象中被设置。
public class PointOne { private Integer x; private Integer y; public PointOne(PointOne point){ this.x = point.x; this.y = point.y; } }
public class PointTwo extends PointOne{ private Integer z; public PointTwo(PointTwo point){ super(point); //Call Super class constructor here this.z = point.z; } }
class Test { public static void main(String[] args) { PointOne one = new PointOne(1,2); PointTwo two = new PointTwo(1,2,3); PointOne clone1 = new PointOne(one); PointOne clone2 = new PointOne(two); //Let check for class types System.out.println(clone1.getClass()); System.out.println(clone2.getClass()); } } Output: class corejava.cloning.PointOne class corejava.cloning.PointOne
public class PointOne implements Cloneable{ private Integer x; private Integer y; public PointOne(Integer x, Integer y) { this.x = x; this.y = y; } public PointOne copyPoint(PointOne point) throws CloneNotSupportedException { if(!(point instanceof Cloneable)) { throw new CloneNotSupportedException("Invalid cloning"); } //Can do multiple other things here return new PointOne(point.x, point.y); } }
@SuppressWarnings("unchecked") public static T clone(T t) throws Exception { //Check if T is instance of Serializeble other throw CloneNotSupportedException ByteArrayOutputStream bos = new ByteArrayOutputStream(); //Serialize it serializeToOutputStream(t, bos); byte[] bytes = bos.toByteArray(); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); //Deserialize it and return the new instance return (T)ois.readObject(); }
SomeObject cloned = org.apache.commons.lang.SerializationUtils.clone(someObject);
if(obj1 instanceof Cloneable){ obj2 = obj1.clone(); } //Dont do this. Cloneabe dont have any methods obj2 = (Cloneable)obj1.clone();
原文地址:http://howtodoinjava.com/2012/11/08/a-guide-to-object-cloning-in-java/