Object 中有一个projected clone() 方法,所以很多类都支持这个“自我克隆”的方法。自定义类想实现clone() 方法只需要实现Cloneable接口即可。它跟Serializable一样,里面没有任何方法,只是一个标志性的接口。一般来讲,利用clone() 可以复制出一个一模一样的实例,而且两者完全隔离。因为它是直接在内存中,将所有数据拷贝一份到另外的区域,效率很高。根据这个原理,我们可以想到这样的问题:如果这个实例包含引用型变量呢?聪明的你应该已经猜到答案了,我们来验证一下。
package testClone;
public class Person {
public String name;
public Person(String n) {
name = n;
}
}
package testClone;
public class Family implements Cloneable {
public Person father;
public Person mother;
public Person son;
public int familyNum;
public Family(Person f, Person m, Person s) {
father = f;
mother = m;
son = s;
familyNum = 3;
}
@Override
protected Family clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return (Family) super.clone();
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Father: " + father.name + "; Mother: " + mother.name + " Son: " + son.name + "; " + "Family Number: "
+ familyNum;
}
}
package testClone;
public class TestClone {
public static void main(String[] args) {
Person father = new Person("Dave1");
Person mother = new Person("Nancy");
Person son = new Person("Jhon");
Family f1 = new Family(father, mother, son);
System.out.println("一开始f1的数据情况是:");
System.out.println(f1.toString() + "\n");
father.name = "Dave2";
System.out.println("通过Person实例,修改father的name:");
System.out.println(f1.toString() + "\n");
f1.father.name = "Dave3";
System.out.println("通过Family实例,修改father的name:");
System.out.println(f1.toString() + "\n");
try {
Family f2 = f1.clone();
f2.father.name = "Dave4";
System.out.println("通过f2实例,修改father的name,看一看对f1有影响吗?");
System.out.println(f1.toString() + "\n");
f2.familyNum = 6;
System.out.println("通过f2实例,修改familyNum,看一看对f1有影响吗?");
System.out.println(f1.toString() + "\n");
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果
所以,对于clone() 要小心成员变量是引用型变量的情况。

350

被折叠的 条评论
为什么被折叠?



