一、若是一個類沒有實現Cloneable接口,直接調用clone()方法,會報異常CloneNotSupportedException,這一點已經在Object源碼中寫道:java
*/ide
protected native Object clone() throws CloneNotSupportedException;工具
並且,源碼也寫到Object的clone()方法是淺拷貝的,這一點在以前的Object源碼分析中我已經寫過了.源碼分析
二、自定義類實現深拷貝方法有2種,下面依次給出具體寫法。測試
2.一、自定義類要實現Cloneable接口,並覆寫clone()方法。this
/**.net
*/code
//測試類1對象
class Person implements Cloneable{blog
String name;
int age;
Person(String name,int age){
this.name=name;
this.age=age;
}
@Override
public Object clone() {
try{
return super.clone();
}catch(CloneNotSupportedException e){
return null;
}
}
}
//測試類2
class Animal implements Cloneable{
Person host;//主人
int age;//年紀
Animal(Person person,int age){
this.host=person;
this.age=age;
}
@Override
public Object clone(){
try{
Animal animal=(Animal) super.clone();
animal.host=(Person)host.clone();//深拷貝處理
return animal;
}catch (CloneNotSupportedException e){
return null;
}
}
}
//測試
public class Main{
public static void main(String[] args) {
Person person1=new Person("cxh",26);
Person person2=(Person)person1.clone();
System.out.println("----------------淺拷貝--------------");
//測試Object的clone方法爲淺拷貝
//String類用==測試內存地址是否一致
System.out.println("person1和person2的name內存地址是否相同:"+(person1.name==person2.name));
System.out.println("----------------深拷貝--------------");
//重寫Object的clone方法,實現深拷貝
//仍是用==查看兩個對象的內存地址是否相等來肯定是否爲兩個對象,若是是兩個內存地址,那麼就是深拷貝
Animal animal1=new Animal(new Person("cxh",26),3);
Animal animal2=(Animal) animal1.clone();
System.out.println("animal1和animal2的host內存地址是否相同:"+(animal1.host==animal2.host));
}
}
輸出:
----------------淺拷貝--------------
person1和person2的name內存地址是否相同:true
----------------深拷貝--------------
animal1和animal2的host內存地址是否相同:false
Process finished with exit code 0
一個講解很詳細的博客:http://blog.csdn.net/zhangjg_...
2.二、經過序列化方式實現深拷貝:先將要拷貝對象寫入到內存中的字節流中,而後再從這個字節流中讀出剛剛存儲的信息,做爲一個新對象返回,那麼這個新對象和原對象就不存在任何地址上的共享,天然實現了深拷貝。
自定義類須要實現Serializable接口。
import java.io.*;
/**
*/
//工具類
class CloneUtil{
public static <T extends Serializable> T clone(T obj){
T cloneObj=null;
try{
//寫入字節流
ByteArrayOutputStream baos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
//分配內存,寫入原始對象,生成新對象
ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());//獲取上面的輸出字節流
ObjectInputStream ois=new ObjectInputStream(bais);
//返回生成的新對象
cloneObj=(T)ois.readObject();
ois.close();
}catch (Exception e){
e.printStackTrace();
}
return cloneObj;
}
}
//測試類1
class Person implements Serializable{
String name;
int age;
Person(String name,int age){
this.name=name;
this.age=age;
}
}
//測試類2
class Animal implements Serializable{
Person host;//主人
int age;//年紀
Animal(Person person,int age){
this.host=person;
this.age=age;
}
}
//測試
public class Main{
public static void main(String[] args) {
System.out.println("----------------深拷貝--------------");
//重寫Object的clone方法,實現深拷貝
//仍是用==查看兩個對象的內存地址是否相等來肯定是否爲兩個對象,若是是兩個內存地址,那麼就是深拷貝
Animal animal1=new Animal(new Person("cxh",26),3);
Animal animal2=CloneUtil.clone(animal1);
System.out.println("animal1和animal2的host內存地址是否相同:"+(animal1.host==animal2.host));
}
}
輸出結果:
----------------深拷貝--------------
animal1和animal2的host內存地址是否相同:false