本文首發於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
這也是昨天的面試題。git
當時只說了深拷貝以及淺拷貝,面試官問了兩遍還有嗎,我很確定的說就這兩種了,面試結束以後查了一下,啪啪打臉。github
JAVA實現克隆有兩種形式面試
JAVA將數據類型分爲基本數據類型以及引用數據類型,我認爲淺克隆與深克隆的區別主要在於對引用類型的成員屬性的操做。深度克隆應該遞歸克隆引用類型的成員屬性。ide
代碼post
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()); } }
輸出this
name1 name2
結果分析code
由於只是直接調用父類的clone方法,沒有對成員屬性進行處理,因此在修改t1屬性name的值時,t2屬性name的值也會隨之改變。對象
優勢blog
簡單易實現
缺點
沒法真正克隆對象
代碼
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對象克隆共有兩種形式,三種方法
淺克隆
深克隆
三種方法之間互有優缺點,具體採用要根據實際狀況。