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

歡迎訪問 生活随笔!

生活随笔

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

java

Java中克隆的用法,深拷贝、浅拷贝概念的引出

發布時間:2023/12/14 java 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中克隆的用法,深拷贝、浅拷贝概念的引出 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一 什么是克隆

克隆就是根據已有對象復制出另一個對象。比如用A克隆出B,一般在java中有如下約定:

// A與B的引用不同 A!=B // A與B的類相同 A.getClass == B.getClass // A和B內容相同 A.equals(B)通常來說 A.equals(B) == true,但是這不是強制的要求,開發人員可根據具體需要決定是否重寫equals方法。

二 怎么實現克隆

需要克隆的類 實現 Cloneable 接口,并重寫其中的clone方法。其中super.clone()會把原始對象的屬性克隆到新對象的屬性中。

public class Student1 implements Cloneable{private String name;private int age;public Student1(String name, int age) {this.name = name;this.age = age;}@Overrideprotected Student1 clone() throws CloneNotSupportedException {return (Student1)super.clone();} }

測試程序如下:

public class TestClone {public static void main(String[] args) {Student1 xiaoming = new Student1(new String("小明"),12);Student1 xiaoming_Copy = null;try {xiaoming_Copy = xiaoming.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}System.out.println(xiaoming.toString());System.out.println(xiaoming_Copy.toString());} }

輸出:

{“age”:12,”name”:”小明”}
{“age”:12,”name”:”小明”}

這樣Student的克隆成功了。

實際上,Cloneable是個空接口,它沒有定義任何成員。它只是一個對象可重寫并使用clone方法的標志。

public interface Cloneable { }

三 這樣就結束了嗎??

如果一個類中的域(屬性)都是基本數據類型或者final類型當然就沒有問題了,但是如果一個類的域是非final類型的引用類型(比如:數組、其他對象)。那么這樣克隆就會出現一個問題,先看一個例子:
新加了一個Teacher類:

public class Teacher {private String name;private int age;public Teacher(String name, int age) {this.name = name;this.age = age;}

Stuent類中加入Teacher屬性:

public class Student2 implements Cloneable {private String name;private int age;private Teacher teacher;public Student2(String name, int age, Teacher teacher) {this.name = name;this.age = age;this.teacher = teacher;}@Overrideprotected Student2 clone() throws CloneNotSupportedException {return (Student2)super.clone();}

運行下面的測試程序:

public class TestClone {public static void main(String[] args) {Teacher teacher = new Teacher("王尼瑪",41);Student2 xiaoming = new Student2(new String("小明"),12,teacher);Student2 xiaoming_Copy = null;try {xiaoming_Copy = xiaoming.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}xiaoming_Copy.getTeacher().setName("齊東強");System.out.println(xiaoming.toString());System.out.println(xiaoming_Copy.toString());} }

輸出

{“age”:12,”name”:”小明”,”teacher”:{“age”:41,”name”:”齊東強”}}
{“age”:12,”name”:”小明”,”teacher”:{“age”:41,”name”:”齊東強”}}

發現拷貝對象副本在改變自己屬性的時候會影響原始主本的數據,這是因為super.clone()只會把Student中對Teacher的引用值copy給克隆對象。所以主本和副本中的teacher對象指向了相同的堆地址。顯然這不是我們想要的。

四 如何解決

嵌套多少層非final類型的引用,我們就拷貝多少層!
Teacher也 實現 Cloneable類,添加clone方法

public class Teacher implements Cloneable{private String name;private int age;public Teacher(String name, int age) {this.name = name;this.age = age;}@Overrideprotected Teacher clone() throws CloneNotSupportedException {return (Teacher)super.clone();}}

修改Student中的clone方法為:

@Overridepublic Student2 clone() throws CloneNotSupportedException {Student2 copy = (Student2)super.clone();copy.teacher = teacher.clone();return copy;}

再次運行測試程序

{“age”:12,”name”:”小明”,”teacher”:{“age”:41,”name”:”王尼瑪”}}
{“age”:12,”name”:”小明”,”teacher”:{“age”:41,”name”:”齊東強”}}
這次修改克隆對象的引用屬性,原對象就不會被改變了

五 總結

其實三中的demo被稱為淺克隆(淺拷貝),四中的解決方案為深克隆(深拷貝)

5.1 淺拷貝

淺拷貝是指拷貝對象時僅僅拷貝對象本身(包括對象中的基本變量),而不拷貝對象包含的非final引用類型屬性指向的對象

public Object clone() {return super.clone();}

直接使用super.clone()方法。

5.2 深拷貝

深拷貝不僅拷貝對象本身,而且拷貝對象包含的引用指向的所有對象

public Object clone() {Object obj = super.clone();//先淺拷貝一下//然后修正需要修正的屬性obj.屬性1 = xxx;obj.屬性2 = xxx;...}

5.3 如何選擇使用哪種拷貝方式

1.如果類中的屬性只包含有基本數據類型常量(包括String),那么這個類使用淺拷貝。

使用淺拷貝的類也可能需要修正,譬如代表序列號、其他唯一ID、對象的創建時間的屬性,不管這些屬性是基本類型還是常量,都需要修正。(常量需要修正時,不能使用super.clone()

2.如果類中的屬性包含有非final的引用類型時(String不算),使用深拷貝,不然拷貝對象的改變會影響原對象,就失去了拷貝的意義。

5.4 什么時候使用克隆

  • 當你想獲取某個對象的數據內容,對其進行一系列操作又不想改變其內容時。
  • 直接用構造器新生成一個對象的代價太大時。
  • 總結

    以上是生活随笔為你收集整理的Java中克隆的用法,深拷贝、浅拷贝概念的引出的全部內容,希望文章能夠幫你解決所遇到的問題。

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