摘要:優(yōu)點簡單易實現(xiàn)缺點無法真正克隆對象深克隆實現(xiàn)通過遞歸克隆實現(xiàn)代碼輸出通過序列化實現(xiàn)代碼輸出結(jié)果分析采用深克隆能有效隔離源對象與克隆對象的聯(lián)系。
本文首發(fā)于cartoon的博客 ????
轉(zhuǎn)載請注明出處: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/
這也是昨天的面試題。
當時只說了深拷貝以及淺拷貝,面試官問了兩遍還有嗎,我很肯定的說就這兩種了,面試結(jié)束之后查了一下,啪啪打臉。
正文JAVA實現(xiàn)克隆有兩種形式
淺克隆
深克隆
JAVA將數(shù)據(jù)類型分為基本數(shù)據(jù)類型以及引用數(shù)據(jù)類型,我認為淺克隆與深克隆的區(qū)別主要在于對引用類型的成員屬性的操作。深度克隆應該遞歸克隆引用類型的成員屬性。
實現(xiàn)Cloneable接口
重寫clone方法,調(diào)用父類的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
結(jié)果分析
因為只是直接調(diào)用父類的clone方法,沒有對成員屬性進行處理,所以在修改t1屬性name的值時,t2屬性name的值也會隨之改變。
優(yōu)點
簡單易實現(xiàn)
缺點
無法真正克隆對象
代碼
?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
結(jié)果分析
采用深克隆能有效隔離源對象與克隆對象的聯(lián)系。
從實現(xiàn)過程來說,遞歸克隆存在克隆過程多且復雜的缺點,所以建議采用序列化的方式進行
深克隆。
總結(jié)JAVA對象克隆共有兩種形式,三種方法
淺克隆
調(diào)用clone方法
深克隆
遞歸調(diào)用clone方法
序列化對象
三種方法之間互有優(yōu)缺點,具體采用要根據(jù)實際情況。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/77829.html
摘要:不合規(guī)的代碼示例合規(guī)解決方案參閱復制構(gòu)造函數(shù)與克隆也可以參閱應該實現(xiàn)克隆覆蓋的類應為并調(diào)用下面為引文翻譯談設(shè)計與作者的對話,作者首次在上發(fā)表,年月日復制構(gòu)造函數(shù)與克隆在你的書中,你建議使用復制構(gòu)造函數(shù)而不是實現(xiàn)和編寫。 今天在用 sonar 審核代碼, 偶然看到下面的提示:showImg(https://segmentfault.com/img/bVbqioZ?w=858&h=116)...
摘要:主要內(nèi)容清楚對象克隆的操作結(jié)構(gòu)鞏固接口的作用具體內(nèi)容對象克隆對象克隆指的就是對象的復制操作,在類里面提供有一個專門克隆的方法。此方法上拋出一個異常,如果要使用對象克隆的類沒有實現(xiàn)接口,那么就會拋出此異常。 主要內(nèi)容 清楚對象克隆的操作結(jié)構(gòu)鞏固接口的作用具體內(nèi)容 對象克隆 對象克隆指的就是對象的復制操作,在Object類里面提供有一個專門克隆的方法。 對象克?。簆rotected Obj...
摘要:定義給出的原型模式定義如下使用原型實例指定將要創(chuàng)建的對象類型,通過復制這個實例創(chuàng)建新的對象。具體原型類角色負責實現(xiàn)復制現(xiàn)有實例并生成新實例的方法。 Java面試通關(guān)手冊(Java學習指南,歡迎Star,會一直完善下去,歡迎建議和指導):https://github.com/Snailclimb/Java_Guide 系列文章回顧: 設(shè)計模式專欄深入理解單例模式深入理解工廠模式 深入理解...
摘要:目錄介紹問題匯總具體問題好消息博客筆記大匯總年月到至今,包括基礎(chǔ)及深入知識點,技術(shù)博客,學習筆記等等,還包括平時開發(fā)中遇到的匯總,當然也在工作之余收集了大量的面試題,長期更新維護并且修正,持續(xù)完善開源的文件是格式的同時也開源了生活博客,從年 目錄介紹 00.Java問題匯總 01.具體問題 好消息 博客筆記大匯總【16年3月到至今】,包括Java基礎(chǔ)及深入知識點,Android技...
摘要:有一些設(shè)計缺陷,其中最大的一個是接口沒有方法。這基本上就是你用復制構(gòu)造函數(shù)做的事情。復制構(gòu)造方法有幾個優(yōu)點,我在本書中有討論。的方法是非常棘手的。它創(chuàng)建一個對象而不調(diào)用構(gòu)造函數(shù)。無法保證它保留構(gòu)造函數(shù)建立的不變量。 前言 在Java API中,可以通過實現(xiàn)Cloneable接口并重寫clone方法實現(xiàn)克隆,但Java設(shè)計者否定了使用clone創(chuàng)建新對象的方法. 1. clone方法實現(xiàn)...
閱讀 2788·2021-11-02 14:42
閱讀 3171·2021-10-08 10:04
閱讀 1192·2019-08-30 15:55
閱讀 1035·2019-08-30 15:54
閱讀 2327·2019-08-30 15:43
閱讀 1688·2019-08-29 15:18
閱讀 871·2019-08-29 11:11
閱讀 2370·2019-08-26 13:52