Java Cloneable介面的深拷貝與淺拷貝方法
Cloneable介面原始碼
Cloneable介面:
實作此介面的類別——可被推斷java.lang.Object
的clone()方法可以被合法地呼叫-以實作類別實例:屬性到屬性的拷貝。
如果一個類別未實作Cloneable介面,那麼呼叫clone()方法時,會拋出CloneNotSupportedException異常。
通常,實作了Cloneable介面的子類別,應當以public存取權重寫clone()方法(儘管java.Object類別中的clone方法是protected類型的)
應當認識到:Cloneable介面沒有包含clone()方法,因此,如果僅僅是implements了Cloneable介面,那麼也是無法正常複製物件的
[原因:即使是反射性地呼叫了克隆方法,也不能保證它一定會成功]——個人理解就是:是否重寫Clone()方法、或「淺拷貝與深拷貝」問題的存在所導致的。
class Pet implements Cloneable{ //properties private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } public Pet() { } public Pet(String name) { this.name = name; } @Override public String toString() { return "Pet{" + "name='" + name + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Pet pet = (Pet) o; return Objects.equals(name, pet.name); } @Override public int hashCode() { return Objects.hash(name); } // @Override // public Pet clone() { // try { // return (Pet)super.clone(); // } catch (CloneNotSupportedException e) { // e.printStackTrace(); // } // return null; // } }
淺拷貝案例
Pet類別定義
#注意到:Pet類別實作了Cloneable接口,但是沒有重寫Clone()方法(顯然:此時Pet類別不具備物件克隆的能力)。
class Pet implements Cloneable{ //properties private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } public Pet() { } public Pet(String name) { this.name = name; } @Override public String toString() { return "Pet{" + "name='" + name + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Pet pet = (Pet) o; return Objects.equals(name, pet.name); } @Override public int hashCode() { return Objects.hash(name); } // @Override // public Pet clone() { // try { // return (Pet)super.clone(); // } catch (CloneNotSupportedException e) { // e.printStackTrace(); // } // return null; // } }
Person類別定義
注意到:Person類別實作了Cloneable接口,也重寫Clone()方法。那麼,是否Person類別就具備了物件克隆的能力呢? (由於淺拷貝問題的存在,認為這種物件克隆能力是不完整的、有缺陷的)。
class Pet implements Cloneable{ //properties private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } public Pet() { } public Pet(String name) { this.name = name; } @Override public String toString() { return "Pet{" + "name='" + name + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Pet pet = (Pet) o; return Objects.equals(name, pet.name); } @Override public int hashCode() { return Objects.hash(name); } // @Override // public Pet clone() { // try { // return (Pet)super.clone(); // } catch (CloneNotSupportedException e) { // e.printStackTrace(); // } // return null; // } }
淺拷貝問題-程式碼測試
為什麼說:此時Person類別的物件克隆能力是不完整的、有缺陷的?因為此時,在透過Person物件呼叫clone()方法,複製物件時,其成員屬性pet(Pet類別的物件)值的克隆,僅僅是對堆區記憶體位址的簡單拷貝。
即:說白了,Person對象和克隆出來的對象,其pet屬性值共享同一塊堆區記憶體。 ——問題顯而易見:當對複製出來的物件的pet屬性進行set操作時,顯然會影響到原始Person物件的pet屬性值。
程式碼示範如下:
//methods public static void main(String[] args) throws CloneNotSupportedException { testPerson(); } public static void testPerson() throws CloneNotSupportedException { Person p=new Person("张三",14,new Pet("小黑")); System.out.println(p); Person clone = (Person)p.clone(); System.out.println(clone); System.out.println(p.equals(clone)); System.out.println(p.getPet()==clone.getPet()); System.out.println("************"); clone.setAge(15); System.out.println(p); System.out.println(clone); System.out.println(p.equals(clone)); System.out.println("************"); clone.getPet().setName("小黄"); System.out.println(p); System.out.println(clone); System.out.println(p.equals(clone)); System.out.println(p.getPet()==clone.getPet()); }
#深拷貝案例
那麼,要如何實現深拷貝呢?關鍵就在上述案例中,被註解的幾行程式碼中。
Pet類別重寫clone()方法
#Person的clone()方法中呼叫Pet的clone方法
淺拷貝問題解決-深拷貝程式碼測試
測試程式碼不變,再執行一次:
以上是Java Cloneable介面的深拷貝與淺拷貝方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4
