简述:
1. 研究一下Java中浅复制和深复制的区别及一些特性
2.分别用普通的clone方法和串行化(Serialization)方法实现深复制
浅复制:
被复制对象的所有变量都含有与原来的对象相同的值,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
深复制:
被复制对象的所有变量都含有与原来的对象相同的值, 同时复制它所引用的所有对象
测试1(普通的clone()方法实现深复制:
深复制的实现, Person类中有一个PersonInfo的成员,用来表示Person的信息,重写了Clone()的方法之后, 形成了深复制,
person1.clone()的过程中,新建了一个person1所引用的personInfo对象,并把包括引用在内生成的一个新的对象传给了person2
之后修改person1的personInfo, 并不影响person2中的personInfo的信息(因为person2 中的personInfo是新建的一个对象,同时被
person2 的personInfo引用了)
其实就是在clone函数中新增一个对clone对象的成员的新的引用的创建
o.personInfo = (PersonInfo)personInfo.clone();
PersonInfo.java
package test.deep.clone; public class PersonInfo implements Cloneable{ private String name; private int age; PersonInfo(String name, int age){ this.name = name; this.age = age; } @Override protected Object clone() throws CloneNotSupportedException { Object o = null; try{ o = super.clone(); }catch(CloneNotSupportedException e){ System.out.println(e.toString()); } return o; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Person.java
package test.deep.clone; public class Person implements Cloneable{ private PersonInfo personInfo; Person(PersonInfo personInfo){ this.personInfo = personInfo; } public PersonInfo getPersonInfo() { return personInfo; } public void setPersonInfo(PersonInfo personInfo) { this.personInfo = personInfo; } @Override protected Object clone() throws CloneNotSupportedException { Person o = null; try{ o = (Person)super.clone(); }catch(CloneNotSupportedException e){ System.out.println(e.toString()); } o.personInfo = (PersonInfo)personInfo.clone(); return o; } }
Test.java(测试)
package test.deep.clone; public class Test { public static void main(String[] args) { PersonInfo personInfo1 = new PersonInfo("Peter", 20); Person person1 = new Person(personInfo1); Person person2 = null; try { person2 = (Person) person1.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } //change the personInfo of person1 person1.setPersonInfo(new PersonInfo("John", 30)); System.out.println("person1=> name: " + person1.getPersonInfo().getName() + ", age: " + person1.getPersonInfo().getAge()); //Due to the deep duplication of person1, the previous personInfo modification on person1 //didn't have any effect on person2 (person2 is a new Object from clone); System.out.println("person2=> name: " + person2.getPersonInfo().getName() + ", age: " + person2.getPersonInfo().getAge()); } }
测试一普通clone()输出:
由于是新建了一个person2对象,及其personInfo的新的引用所以在修改该person1中personInfo变量的时候,对person2无影响
测试2
使用串行化(Serialization)实现深复制
(串行化:对象通过写出描述自己状态的数值来记录自己,这个过程叫对象的串行化)
PersonInfo.java
package test.clone.deep.serialization; import java.io.Serializable; public class PersonInfo implements Serializable{ private static final long serialVersionUID = 1L; private String name; private int age; PersonInfo(String name, int age){ this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
package test.clone.deep.serialization; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class Person implements Serializable{ private static final long serialVersionUID = 1L; private int id ; private PersonInfo personInfo; Person(int id, PersonInfo personInfo){ this.id = id; this.personInfo = personInfo; } public void setId(int id) { this.id = id; } public int getId() { return id; } public PersonInfo getPersonInfo() { return personInfo; } public void setPersonInfo(PersonInfo personInfo) { this.personInfo = personInfo; } public Object DeepClone(){ //write the object to stream ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = null; try { objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); } catch (IOException e) { System.out.println("ObjectOutputStream open fail! "); } try { objectOutputStream.writeObject(this); } catch (IOException e) { System.out.println("ObjectOutputStream write object fail! "); } //read the object from stream Object o = null; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); ObjectInputStream objectInputStream = null; try { objectInputStream = new ObjectInputStream(byteArrayInputStream); } catch (IOException e) { System.out.println("ObjectInputStream open fail! "); } try { o = objectInputStream.readObject(); } catch (IOException e) { System.out.println("ObjectInputStream read object fail! "); } catch (ClassNotFoundException e) { System.out.println("ObjectOutputStream class not found!"); } return o; } }
package test.clone.deep.serialization; public class Test { public static void main(String[] args) { System.out.println("Serialization implements deep clone: "); PersonInfo personInfo1 = new PersonInfo("Peter", 20); Person person1 = new Person(1, personInfo1); Person person2 = null; person2 = (Person) person1.DeepClone(); person2.setId(2); //change the personInfo of person1 person2.setPersonInfo(new PersonInfo("John", 30)); System.out.println("person1=> id: " + person1.getId() + ", name: " + person1.getPersonInfo().getName() + ", age: " + person1.getPersonInfo().getAge()); //Due to the deep duplication of person1, the previous personInfo modification on person1 //didn't have any effect on person2 (person2 is a new Object from clone); System.out.println("person2=> id: " + person2.getId() + ", name: " + person2.getPersonInfo().getName() + ", age: " + person2.getPersonInfo().getAge()); } }
串行化实现深复制输出: