clone对象的使用场景:
有一个对象 A,在某一时刻 A 中已经包含了一些有效值,此时可能会需要一个和 A 完全相同新对象 B,并且此后对 B 任何改动都不会影响到 A 中的值,也就是说, A 与 B 是两个独立的对象,但 B 的初始值是由 A 对象确定的。在 Java 语言中,用简单的赋值语句是不能满足这种需求的。要满足这种需求虽然有很多途径,但实现 clone()方法是其中最简单,也是最高效的手段。
clone对象的过程:
clone 在第一步是和 new 相似的,都是分配内存,调用 clone 方法时,分配的内存和原对象(即调用 clone 方法的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域,填充完成之后, clone 方法返回,一个新的相同的对象被创建,同样可以把这个新对象的引用发布到外部。
public class Person implements Cloneable{ private int age; private String name; public Person(int age,String name){ this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return (Person)super.clone(); } public static void main(String[] args) throws Exception { Person p = new Person(3,"xiaoming"); Person p1 = p; Person p2 = (Person) p.clone(); System.out.println(p); System.out.println(p1); System.out.println(p2); } }运行结果:
由结果可以知道,Person p1 = p;只是复制了对象的引用.clone()才是创建了新对象.
深拷贝和浅拷贝:
如Person类的name属性是String类型的,那么在拷贝过程中可以直接复制一份name的引用给clone的新对象,也可以重新创建一个字符串,把新字符串的引用给新对象.这两种拷贝方式就是浅拷贝和深拷贝.
public static void main(String[] args) throws Exception { Person p = new Person(3,"xiaoming"); Person p1 = p; Person p2 = (Person) p.clone(); System.out.println(p); System.out.println(p1); System.out.println(p2); System.out.println(p.name == p2.name);------true }
最后一行运行结果为:true.
说明这里的clone为浅拷贝.
如果想要深拷贝一个对象,这个对象必须要实现 Cloneable 接口,实现 clone方法,并且在 clone 方法内部,把该对象引用的其他对象也要 clone 一份,这就要求这个被引用的对象必须也要实现Cloneable 接口并且实现 clone 方法。