今天有人給我發(fā)來一道題,說的是clone()是深拷貝還是淺拷貝,兩眼懵比。既然不懂,那就寫代碼做個(gè)記錄吧。
首先,了解一下深拷貝和淺拷貝的概念。
當(dāng)一個(gè)對(duì)象被拷貝時(shí),拷貝得到的對(duì)象內(nèi)部的引用對(duì)象和原對(duì)象內(nèi)部的引用對(duì)象地址相等,這是淺拷貝。反之,是深拷貝。
一個(gè)對(duì)象能被拷貝,需要兩個(gè)條件:
- 實(shí)現(xiàn)
Cloneable接口。
該接口是個(gè)空接口,實(shí)現(xiàn)該接口只是使拷貝變得合法,不然會(huì)拋異常java.lang.CloneNotSupportedException。 - 復(fù)寫
clone()方法。
接下來用代碼驗(yàn)證:
public class Animal implements Cloneable {
public Cat cat;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Cat {
}
測(cè)試類:
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
Animal a = new Animal();
a.cat = new Cat();
Animal clone = (Animal) a.clone();
System.out.println("Animal: " + (a == clone));
System.out.println("cat:" + (a.cat == clone.cat));
}
}
打印結(jié)果:
Animal: false
cat:true
一開始的問題有答案了,clone()方法是淺拷貝,兩個(gè)對(duì)象中的cat指向堆中同一個(gè)對(duì)象。
如果想要深拷貝呢?
這時(shí)候就需要改造clone方法了,以及引用的對(duì)象中也要實(shí)現(xiàn)接口和復(fù)寫方法。
上代碼:
public class Animal implements Cloneable {
public Cat cat;
@Override
protected Object clone() throws CloneNotSupportedException {
Animal clone = (Animal) super.clone();
// 引用對(duì)象也拷貝一份
clone.cat = (Cat) cat.clone();
return clone;
}
}
public class Cat implements Cloneable {
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
依舊是上面的測(cè)試代碼,打印結(jié)果為:
Animal: false
cat:false
以上。