您好,登錄后才能下訂單哦!
本篇內容主要講解“Java Cloneable接口的深拷貝與淺拷貝方法”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java 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類實現了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類實現了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()); }
那么,如何實現深拷貝呢?關鍵就在上述案例中,被注釋的幾行代碼中。
測試代碼不變,再次運行:
到此,相信大家對“Java Cloneable接口的深拷貝與淺拷貝方法”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。