这也是昨天的面试题。
当时只说了深拷贝以及浅拷贝,面试官问了两遍还有吗,我很肯定的说就这两种了,面试结束之后查了一下,啪啪打脸。
JAVA实现克隆有两种形式
JAVA将数据类型分为基本数据类型以及引用数据类型,我认为浅克隆与深克隆的区别主要在于对引用类型的成员属性的操作。深度克隆应该递归克隆引用类型的成员属性。
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对象克隆共有两种形式,三种方法
浅克隆
深克隆
三种方法之间互有优缺点,具体采用要根据实际情况。