日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java的深浅拷贝你了解吗?

發布時間:2024/2/28 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java的深浅拷贝你了解吗? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、概述

拷貝的一個經典的使用場景:當前對象要傳給其他多個方法使用,如果該對象在某一個方法中被修改,那么這個修改會影響到其他方法。 如果要避免這種影響,就需要給每一個方法都傳入一個當前對象的拷貝。

深與淺拷貝的區別就在于對復雜對象的處理:對于基本類型,淺拷貝、深拷貝都是拷貝的值;對于引用類型淺拷貝的是對象的引用。而深拷貝則是直接新建一個對象實例。

?

注意淺拷貝中的復雜引用以及簡單引用:對于簡單引用,拷貝后的對象指向新的地址不會影響到原對象。復雜引用,拷貝后的對象將內部的對象指向新的地址,影響到原對象對應的內部對象。這里一定理解下,抓住“地址”指向去理解就好了。

?

?

2、代碼實現

(1)淺拷貝實現方式:類實現Cloneable接口,并且重寫clone()方法。詳細見下面的代碼

(2)深拷貝:主要是針對類內部的復雜引用變量。兩種方式:1)復雜引用也實現Cloneable,并重寫clone()方法,然后在父對象重寫的clone方法中將該復雜引用指向克隆后的引用? 2)直接將需要克隆的對象進行序列化,然后反序列化就可以得到一個深拷貝的對象。

當然這些工作都有現成的輪子了,借助于Apache Commons工具類可以直接實現:

  • 淺克隆:BeanUtils.cloneBean(Object obj);
  • 深克隆:SerializationUtils.clone(T object);

當然可以直接使用

2.1淺拷貝

父子類

1 @Data2 @Builder3 class Father implements Cloneable {4 Long age;5 StringBuilder name;6 Son son;7 8 @Override9 public Object clone() { 10 //淺拷貝 11 try { 12 return super.clone(); 13 } catch (CloneNotSupportedException e) { 14 e.printStackTrace(); 15 return null; 16 } 17 } 18 } 19 20 @Data 21 @Builder 22 class Son { 23 Long age; 24 String name; 25 int grade; 26 }

?

?

初始賦值

1 public static Son son = Son.builder().age(new Long(30L)).name("大兒子").grade(100).build(); 2 public static Father father = Father.builder().age(new Long(50L)).name("爸爸").son(son).build();

?

淺拷貝示例:

private static void shallowClone() {System.out.println("父親年齡:" + father.getAge());System.out.println("父親姓名:" + father.getName());System.out.println("兒子年齡:" + father.getSon().getAge());System.out.println("兒子姓名:" + father.getSon().getName());System.out.println("兒子分數:" + father.getSon().getGrade());//開始克隆Father fatherInLaw = (Father) father.clone();fatherInLaw.getSon().setAge(10L);fatherInLaw.getSon().setGrade(0);fatherInLaw.getSon().setName("繼子");fatherInLaw.setAge(new Long(80L));fatherInLaw.setName("繼父");//修改后結果System.out.println("==========淺拷貝后===========");System.out.println("父親年齡:" + father.getAge());System.out.println("父親姓名:" + father.getName());System.out.println("兒子年齡:" + father.getSon().getAge());System.out.println("兒子姓名:" + father.getSon().getName());System.out.println("兒子分數:" + father.getSon().getGrade());}

結果輸出

父親年齡:50 父親姓名:爸爸 兒子年齡:30 兒子姓名:大兒子 兒子分數:100 ==========淺拷貝后=========== 父親年齡:50 父親姓名:爸爸 兒子年齡:10 兒子姓名:繼子 兒子分數:0

?

2.2.深拷貝

(1)子引用重寫clone方法,并且在父類中改變子引用的指向

父子類

@Data @Builder class Father implements Cloneable {Long age;StringBuilder name;Son son;@Overridepublic Object clone() {Father father = null;//淺拷貝try {father = (Father) super.clone();father.son = (Son) son.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}return father;} }@Data @Builder class Son implements Cloneable {Long age;String name;int grade;@Overridepublic Object clone() {//拷貝try {return super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}} }

View Code

賦初值

1 public static Son son = Son.builder().age(new Long(30L)).name("大兒子").grade(100).build(); 2 public static Father father = Father.builder().age(new Long(50)).name(new StringBuilder("爸爸")).son(son).build();

深拷貝示例:

//深拷貝private static void deepClone() {System.out.println("父親年齡:" + father.getAge());System.out.println("父親姓名:" + father.getName());System.out.println("兒子年齡:" + father.getSon().getAge());System.out.println("兒子姓名:" + father.getSon().getName());System.out.println("兒子分數:" + father.getSon().getGrade());//開始克隆Father fatherInLaw = (Father) father.clone();fatherInLaw.getSon().setAge(10L);fatherInLaw.getSon().setGrade(0);fatherInLaw.getSon().setName("繼子");fatherInLaw.setAge(new Long(80L));fatherInLaw.setName(new StringBuilder("繼父"));//修改前System.out.println("==========淺拷貝后===========");System.out.println("父親年齡:" + father.getAge());System.out.println("父親姓名:" + father.getName());System.out.println("兒子年齡:" + father.getSon().getAge());System.out.println("兒子姓名:" + father.getSon().getName());System.out.println("兒子分數:" + father.getSon().getGrade());}

結果

父親年齡:50 父親姓名:爸爸 兒子年齡:30 兒子姓名:大兒子 兒子分數:100 ==========淺拷貝后=========== 父親年齡:50 父親姓名:爸爸 兒子年齡:30 兒子姓名:大兒子 兒子分數:100

(2)序列化方式

父子類

@Data @Builder class Father implements Serializable {Long age;StringBuilder name;Son son;public Object deepClone() throws IOException, ClassNotFoundException {//序列化ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);//反序列化ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return ois.readObject();} }@Data @Builder class Son implements Serializable {Long age;String name;int grade; }

View Code

實現方法

//深拷貝private static void deepCloneV2() throws IOException, ClassNotFoundException {System.out.println("父親年齡:" + father.getAge());System.out.println("父親姓名:" + father.getName());System.out.println("兒子年齡:" + father.getSon().getAge());System.out.println("兒子姓名:" + father.getSon().getName());System.out.println("兒子分數:" + father.getSon().getGrade());//開始克隆Father fatherInLaw = (Father) father.deepClone();fatherInLaw.getSon().setAge(10L);fatherInLaw.getSon().setGrade(0);fatherInLaw.getSon().setName("繼子");fatherInLaw.setAge(new Long(80L));fatherInLaw.setName(new StringBuilder("繼父"));//修改前System.out.println("==========淺拷貝后===========");System.out.println("父親年齡:" + father.getAge());System.out.println("父親姓名:" + father.getName());System.out.println("兒子年齡:" + father.getSon().getAge());System.out.println("兒子姓名:" + father.getSon().getName());System.out.println("兒子分數:" + father.getSon().getGrade());}

結果:

父親年齡:50 父親姓名:爸爸 兒子年齡:30 兒子姓名:大兒子 兒子分數:100 ==========淺拷貝后=========== 父親年齡:50 父親姓名:爸爸 兒子年齡:30 兒子姓名:大兒子 兒子分數:100

3、使用Apach??Commons

3.1實現深拷貝,需要實現序列化接口,SerializationUtils.clone(T object);

父子類

@Data @Builder class Father implements Serializable{Long age;StringBuilder name;Son son; }@Data @Builder class Son implements Serializable{Long age;String name;int grade; }

View Code

實現方法

//深拷貝private static void deepCloneCommons() throws IOException, ClassNotFoundException {System.out.println("父親年齡:" + father.getAge());System.out.println("父親姓名:" + father.getName());System.out.println("兒子年齡:" + father.getSon().getAge());System.out.println("兒子姓名:" + father.getSon().getName());System.out.println("兒子分數:" + father.getSon().getGrade());//開始克隆Father fatherInLaw = (Father) SerializationUtils.clone(father);fatherInLaw.getSon().setAge(10L);fatherInLaw.getSon().setGrade(0);fatherInLaw.getSon().setName("繼子");fatherInLaw.setAge(new Long(80L));fatherInLaw.setName(new StringBuilder("繼父"));//修改前System.out.println("==========淺拷貝后===========");System.out.println("父親年齡:" + father.getAge());System.out.println("父親姓名:" + father.getName());System.out.println("兒子年齡:" + father.getSon().getAge());System.out.println("兒子姓名:" + father.getSon().getName());System.out.println("兒子分數:" + father.getSon().getGrade());}

View Code

結果

父親年齡:50 父親姓名:爸爸 兒子年齡:30 兒子姓名:大兒子 兒子分數:100 ==========深拷貝后=========== 父親年齡:50 父親姓名:爸爸 兒子年齡:30 兒子姓名:大兒子 兒子分數:100

3.2使用工具類實現深拷貝,BeanUtils.copyProperties(Object dest, Object orig)直接調用即可實現淺拷貝,BeanUtils.cloneBean(Object obj)最終也是調用的copyProperties方法。

?

摘自:http://www.manongjc.com/detail/9-vvtzsyvyjxehgdw.html

總結

以上是生活随笔為你收集整理的Java的深浅拷贝你了解吗?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。