複習一下對象的深淺拷貝

一、若是一個類沒有實現Cloneable接口,直接調用clone()方法,會報異常CloneNotSupportedException,這一點已經在Object源碼中寫道:java

  • @return a clone of this instance.
  • @exception CloneNotSupportedException if the object's class does not
  • support the {@code Cloneable} interface. Subclasses
  • that override the {@code clone} method can also
  • throw this exception to indicate that an instance cannot
  • be cloned.
  • @see java.lang.Cloneable

*/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

相關文章
相關標籤/搜索