设计模式之原型模式 (2)

对象中含有引用类型

public class Teacher implements Cloneable{ private String name; private int age; private Student student; public Teacher(String name, int age, Student student){ this.name = name; this.age = age; this.student = student; } // 覆盖 @Override public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } 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; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } } // 学生类 public class Student { private String name; private int age; public Student(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; } } // 客户端测试 public class test { public static void main(String[] args) { Student student = new Student("学生1" ,11); Teacher origin = new Teacher("老师", 11, student);; Teacher clone = (Teacher) origin.clone(); System.out.println("比较克隆后的引用对象"); System.out.println(origin.getStudent().getClass() == clone.getStudent().getClass()); Student student2 = new Student("学生2", 12); clone.setStudent(student2); System.out.println("克隆后,比较克隆对象改变引用"); System.out.println(origin.getStudent().getClass() == clone.getStudent().getClass()); } }

运行结果:

比较克隆后的引用对象
true
克隆后,比较克隆对象改变引用
true

1545109406152

如图可知,引用类型只会存在一份内存地址,执行object的clone方法拷贝的也是引用的复制(这部分的内存空间不一样,)但是引用指向的内存空间是一样的,原对象修改引用变量或者浅拷贝对象修改引用变量都会引起双方的变化

重点:综上两个方面可以知道,Object的clone方法是属于浅拷贝,基本变量类型会复制相同值,而引用变量类型也是会复制相同的引用。

深复制实例

从上面的浅拷贝可以知道,对于引用的变量只会拷贝引用指向的地址,也就是指向同一个内存地址,但是很多情况下我们需要的是下面图的效果:

1545121868853

深拷贝实现的是对所有可变(没有被final修饰的引用变量)引用类型的成员变量都开辟内存空间所以一般深拷贝对于浅拷贝来说是比较耗费时间和内存开销的。

深拷贝的两种方式:

重写clone方法实现深拷贝

学生类:

public class Student implements Cloneable { private String name; private int age; public Student(String name, int age){ this.name = name; this.age = age; } @Override protected Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } 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; } }

老师类:

public class Teacher implements Cloneable{ private String name; private int age; private Student student; public Teacher(String name, int age, Student student){ this.name = name; this.age = age; this.student = student; } // 覆盖 @Override public Object clone() { Teacher t = null; try { t = (Teacher) super.clone(); t.student = (Student)student.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return t; } 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; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } }

测试端:

public class test { public static void main(String[] args) { Student s = new Student("学生1", 11); Teacher origin = new Teacher("老师原对象", 23, s); System.out.println("克隆前的学生姓名:" + origin.getStudent().getName()); Teacher clone = (Teacher) origin.clone(); // 更改克隆后的学生信息 更改了姓名 clone.getStudent().setName("我是克隆对象更改后的学生2"); System.out.println("克隆后的学生姓名:" + clone.getStudent().getName()); } }

运行结果:

克隆前的学生姓名:学生1
克隆后的学生姓名:我是克隆对象更改后的学生2

列化实现深克隆

我们发现上面通过object的clone方法去实现深克隆十分麻烦, 因此引出了另外一种方式:序列化实现深克隆

概念:

序列化:把对象写到流里

反序列化:把对象从流中读出来

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjydf.html