克隆的实现
对象实现Cloneable接口,并实现clone方法
克隆的优点
克隆相对于new一个新对象的时间开销要少,因为clone出的对象不会执行对象的Construstorf方法。这样就节省了一些时间。这是Java 代码优化的一个点。
我们看下代码证明下:
public class Man implements Cloneable{
public Man() {
System.out.println("Man constructor");
}
private Head head;
public Head getHead() {
return head;
}
public void setHead(Head head) {
this.head = head;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Main测试
public static void main(String[] args) throws CloneNotSupportedException {
Man man = new Man();
Head head = new Head();
man.setHead(head);
Man clone = (Man)man.clone();
}
输出结果为
Man constructor
深克隆、浅克隆
我们知道一个对象成员变量有两种类型,一个是基础类型,一个是引用类型。基础类型的数据是存储在栈中的,引用类型的数据是存储在堆中。浅克隆代表的意义是克隆出来的对象的引用类型的成员变量和源对象的成员变量其实指向的是同一个堆对象,即他们equals判断为true.
那我们要如何实现深克隆呢,这就需要我们再引用类型的成员变量的对象中也要实现Cloneable接口,重写clone方法。同时在父对象的clone 方法中 给与成员变量赋值为clone出来的对象,具体看代码
public class Head implements Cloneable{
private Face face;
public Face getFace() {
return face;
}
public void setFace(Face face) {
this.face = face;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Man implements Cloneable{
public Man() {
System.out.println("Man constructor");
}
private Head head;
public Head getHead() {
return head;
}
public void setHead(Head head) {
this.head = head;
}
@Override
public Object clone() throws CloneNotSupportedException {
Man man = (Man)super.clone();
head = (Head)head.clone();
return man;
}
}
测试代码
public static void main(String[] args) throws CloneNotSupportedException {
Man man = new Man();
Head head = new Head();
man.setHead(head);
Man clone = (Man)man.clone();
System.out.println("man 是否是同一个对新"+man.equals(clone));
System.out.println("man.head 是否是同一个引用"+man.getHead().equals(clone.getHead()));
}
结果为:
Man constructor
man 是否是同一个对新false
man.head 是否是同一个引用false
但是我们如果要完全实现深克隆的成本实际是比较高的。因为对象的成员变量的成员变量的成员变量的成员变量。。。。 无线下去,需要所有的成员变量都实现Cloneable,实现clone。并且在父对象都要在clone中设置 xx= xx.clone()
贴个别人博客的图: