摘要:優點簡單易實現缺點無法真正克隆對象深克隆實現通過遞歸克隆實現代碼輸出通過序列化實現代碼輸出結果分析采用深克隆能有效隔離源對象與克隆對象的聯系。
本文首發于cartoon的博客 ????
轉載請注明出處:https://cartoonyu.github.io/cartoon-blog/post/java/java%E5%AE%9E%E7%8E%B0%E5%85%8B%E9%9A%86%E7%9A%84%E6%96%B9%E6%B3%95/
這也是昨天的面試題。
當時只說了深拷貝以及淺拷貝,面試官問了兩遍還有嗎,我很肯定的說就這兩種了,面試結束之后查了一下,啪啪打臉。
正文JAVA實現克隆有兩種形式
淺克隆
深克隆
JAVA將數據類型分為基本數據類型以及引用數據類型,我認為淺克隆與深克隆的區別主要在于對引用類型的成員屬性的操作。深度克隆應該遞歸克隆引用類型的成員屬性。
實現Cloneable接口
重寫clone方法,調用父類的clone方法
代碼
public class Text implements Cloneable{ ?? ? private int age; ?? ? private Name name; ?? ? public int getAge() { ? return age; ? } ?? ? public void setAge(int age) { ? this.age = age; ? } ?? ? public Name getName() { ? return name; ? } ?? ? public void setName(Name name) { ? this.name = name; ? } ?? ? @Override ? protected Object clone(){ ? try { ? return super.clone(); ? } catch (CloneNotSupportedException e) { ? e.printStackTrace(); ? } ? return null; ? } ?} ?? ?class Name{ ? private String name; ?? ? public String getName() { ? return name; ? } ?? ? public void setName(String name) { ? this.name = name; ? } ?} ?? ?public class Main { ?? ? public static void main(String[] args){ ? Name name1=new Name(); ? name1.setName("name1"); ? Text t1=new Text(); ? t1.setAge(12); ? t1.setName(name1); ? Text t2=(Text) t1.clone(); ? System.out.println(t2.getName().getName()); ? name1.setName("name2"); ? System.out.println(t2.getName().getName()); ?? ? } ?? ?}
輸出
name1 name2
結果分析
因為只是直接調用父類的clone方法,沒有對成員屬性進行處理,所以在修改t1屬性name的值時,t2屬性name的值也會隨之改變。
優點
簡單易實現
缺點
無法真正克隆對象
代碼
?public class Text implements Cloneable{ ?? ? private int age; ?? ? private Name name; ?? ? public int getAge() { ? return age; ? } ?? ? public void setAge(int age) { ? this.age = age; ? } ?? ? public Name getName() { ? return name; ? } ?? ? public void setName(Name name) { ? this.name = name; ? } ?? ? @Override ? protected Object clone(){ ? Text text=null; ? try { ? text=(Text) super.clone(); ? } catch (CloneNotSupportedException e) { ? e.printStackTrace(); ? } ? text.setName((Name) text.getName().clone()); ? return text; ? } ?} ?? ?class Name implements Cloneable{ ? private String name; ?? ? public String getName() { ? return name; ? } ?? ? public void setName(String name) { ? this.name = name; ? } ?? ? @Override ? protected Object clone() { ? try { ? return super.clone(); ? } catch (CloneNotSupportedException e) { ? e.printStackTrace(); ? } ? return null; ? } ?}
輸出
name1 name1
代碼
?public class Text implements Serializable{ ?? ? private static final long serialVersionUID = 8723901148964L; ?? ? private int age; ?? ? private Name name; ?? ? public int getAge() { ? return age; ? } ?? ? public void setAge(int age) { ? this.age = age; ? } ?? ? public Name getName() { ? return name; ? } ?? ? public void setName(Name name) { ? this.name = name; ? } ?? ? public Object myClone(){ ? Text text=null; ? ByteArrayOutputStream bos=new ByteArrayOutputStream(); ? try { ? ObjectOutputStream oos=new ObjectOutputStream(bos); ? oos.writeObject(this); ? ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray()); ? ObjectInputStream ois=new ObjectInputStream(bis); ? text=(Text)ois.readObject(); ? } catch (IOException e) { ? e.printStackTrace(); ? } catch (ClassNotFoundException e) { ? e.printStackTrace(); ? } ? return text; ? } ?} ?? ?class Name implements Serializable { ?? ? private static final long serialVersionUID = 872390113109L; ?? ? private String name; ?? ? public String getName() { ? return name; ? } ?? ? public void setName(String name) { ? this.name = name; ? } ?? ? @Override ? public String toString() { ? return name; ? } ?}
輸出
?name1 ?name1
結果分析
采用深克隆能有效隔離源對象與克隆對象的聯系。
從實現過程來說,遞歸克隆存在克隆過程多且復雜的缺點,所以建議采用序列化的方式進行
深克隆。
總結JAVA對象克隆共有兩種形式,三種方法
淺克隆
調用clone方法
深克隆
遞歸調用clone方法
序列化對象
三種方法之間互有優缺點,具體采用要根據實際情況。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77829.html
摘要:不合規的代碼示例合規解決方案參閱復制構造函數與克隆也可以參閱應該實現克隆覆蓋的類應為并調用下面為引文翻譯談設計與作者的對話,作者首次在上發表,年月日復制構造函數與克隆在你的書中,你建議使用復制構造函數而不是實現和編寫。 今天在用 sonar 審核代碼, 偶然看到下面的提示:showImg(https://segmentfault.com/img/bVbqioZ?w=858&h=116)...
摘要:主要內容清楚對象克隆的操作結構鞏固接口的作用具體內容對象克隆對象克隆指的就是對象的復制操作,在類里面提供有一個專門克隆的方法。此方法上拋出一個異常,如果要使用對象克隆的類沒有實現接口,那么就會拋出此異常。 主要內容 清楚對象克隆的操作結構鞏固接口的作用具體內容 對象克隆 對象克隆指的就是對象的復制操作,在Object類里面提供有一個專門克隆的方法。 對象克隆:protected Obj...
摘要:定義給出的原型模式定義如下使用原型實例指定將要創建的對象類型,通過復制這個實例創建新的對象。具體原型類角色負責實現復制現有實例并生成新實例的方法。 Java面試通關手冊(Java學習指南,歡迎Star,會一直完善下去,歡迎建議和指導):https://github.com/Snailclimb/Java_Guide 系列文章回顧: 設計模式專欄深入理解單例模式深入理解工廠模式 深入理解...
摘要:目錄介紹問題匯總具體問題好消息博客筆記大匯總年月到至今,包括基礎及深入知識點,技術博客,學習筆記等等,還包括平時開發中遇到的匯總,當然也在工作之余收集了大量的面試題,長期更新維護并且修正,持續完善開源的文件是格式的同時也開源了生活博客,從年 目錄介紹 00.Java問題匯總 01.具體問題 好消息 博客筆記大匯總【16年3月到至今】,包括Java基礎及深入知識點,Android技...
摘要:有一些設計缺陷,其中最大的一個是接口沒有方法。這基本上就是你用復制構造函數做的事情。復制構造方法有幾個優點,我在本書中有討論。的方法是非常棘手的。它創建一個對象而不調用構造函數。無法保證它保留構造函數建立的不變量。 前言 在Java API中,可以通過實現Cloneable接口并重寫clone方法實現克隆,但Java設計者否定了使用clone創建新對象的方法. 1. clone方法實現...
閱讀 2772·2021-11-02 14:42
閱讀 3162·2021-10-08 10:04
閱讀 1183·2019-08-30 15:55
閱讀 1025·2019-08-30 15:54
閱讀 2310·2019-08-30 15:43
閱讀 1680·2019-08-29 15:18
閱讀 863·2019-08-29 11:11
閱讀 2362·2019-08-26 13:52