1.为什么要克隆?
这无非就是比较克隆的对象与new的对象之间的区别,首先克隆的对象包含一些已经修改过的属性,而new出来的对象的属性都还是初始化时候的值;其次我们以前用过Object a=new Object();Object b=a;这种形式的代码复制的是引用,即对象在内存中的地址,a和b对象仍然指向了同一个对象,而通过clone方法赋值的对象跟原来的对象时同时独立存在的。
2.如何实现克隆?
java的clone分为浅克隆和深克隆。而它们两者的主要区别在于 :是否支持引用类型的成员变量的复制。我们先来看浅克隆,浅克隆的一般步骤如下:
1. 被复制的类需要实现Clonenable接口;
2. 覆盖clone()方法,访问修饰符设为public,方法中调用super.clone()方法得到需要的复制对象。
现在我们按照上面的步骤,写个Demo,代码如下:
public class Student implements Cloneable{
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class TestClone {
public static void main(String[] args) throws CloneNotSupportedException {
Student stu1=new Student();
stu1.setAge(20);
Student stu2=(Student) stu1.clone();
stu2.setAge(10);
Student stu3=stu1;
System.out.println(stu1.getAge()+" "+stu2.getAge());
stu3.setAge(18);
System.out.println(stu1.getAge()+" "+stu3.getAge());
System.out.println(stu1==stu2);
System.out.println(stu3==stu1);
}
}
运行上面的代码,结果如下:
那我们在Student 类加个Pen类成员变量,看看浅克隆会不会复制引用类型的成员变量,代码如下:
public class Pen {
private int price;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
public class TestClone {
public static void main(String[] args) throws CloneNotSupportedException {
Student stu1=new Student();
stu1.setPen(new Pen());
stu1.getPen().setPrice(10);
Student stu2=(Student) stu1.clone();
stu2.getPen().setPrice(18);
System.out.println(stu1.getPen().getPrice()+" "+stu2.getPen().getPrice());
}
}
运行上面的代码,结果如下:
从上面的结果可知,浅克隆不复制引用类型的成员变量,那我们来看下深克隆怎么解决这个问题,代码如下:
public class Pen implements Cloneable{
private int price;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
再次运行代码,结果如下:
从上面的结果可知,深克隆复制引用类型的成员变量 。如果引用类型里面又有许多引用类型,那实现深克隆比较麻烦,这时候可以序列化实现对象的深克隆(可以参考上篇的序列化文章)。