Java中的clone() 深拷贝 浅拷贝

上图展示了浅拷贝:对于非基本数据类型,clone过后,结果两个指针指向了同一块儿内存空间,所以仅仅是浅拷贝,这样的话如果对一个对象进行操作,另一个内容也会变,这显然是不合理的,应该每个对象分别保存自己的数据。

所以我们要进行深拷贝!

浅拷贝和深拷贝例子:

import java.util.Vector;public class Student implements Cloneable{private int id;private String name;private Vector courses;public Student(){try{Thread.sleep(1000);System.out.println("Student Construnctor called");}catch(InterruptedException e){e.printStackTrace();}}public int getId(){return id;}public void setId(int id){this.id=id;}public String getName(){return name;}public void setName(String name){this.name=name;}public Vector getCourses(){return courses;}public void setCourses(Vector courses){this.courses=courses;}public Student newInstance(){ //使用clone()创建对象,浅拷贝try{return (Student)this.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}return null;}public Student deepClone(){//使用clone()创建对象,深拷贝try{Student cloning = (Student) super.clone();//Student cloning = (Strdent) this.clone();//和上一句话效果等价cloning.courses = new Vector();//关键点:非基本数据类型的空间需要自己新开辟一块儿return cloning;}catch(CloneNotSupportedException e){e.printStackTrace();}return null;}}import java.util.Vector;public class Test {public static void main(String[] args) {// TODO Auto-generated method stubStudent stu1 = null;shallowCopyDemo(stu1);System.out.println("—– —– —–I'm cut-off rule—– —– —–");deepCopyDemo(stu1);}public static void shallowCopyDemo(Student stu1) {stu1=new Student();Vector cs=new Vector();cs.add("Java");stu1.setId(1);stu1.setName("Tom");stu1.setCourses(cs);Student stu2=stu1.newInstance();stu2.setId(2);stu2.setName("Mary");stu2.getCourses().add("C#");System.out.println("stu1'name:"+stu1.getName());System.out.println("stu2'name:"+stu2.getName());System.out.println(stu1.getCourses()==stu2.getCourses());System.out.println(stu1.getName + "'s course: " + stu1.getCourses());System.out.println(stu2.getName + "'s course: " + stu2.getCourses());}public static void deepCopyDemo(Student stu1) {stu1=new Student();Vector cs=new Vector();cs.add("Java");stu1.setId(1);stu1.setName("Tom");stu1.setCourses(cs);Student stu2=stu1.deepClone();stu2.setId(2);stu2.setName("Mary");stu2.getCourses().add("C#");System.out.println("stu1'name:"+stu1.getName());System.out.println("stu2'name:"+stu2.getName());System.out.println(stu1.getCourses()==stu2.getCourses());System.out.println(stu1.getName + "'s course: " + stu1.getCourses());System.out.println(stu2.getName + "'s course: " + stu2.getCourses());}}

输出结果:

Student Construnctor calledstu1’name:Tomstu2’name:MarytrueTom’s course: [Java, C#]Mary’s course: [Java, C#]—– —– —–I’m cut-off rule—– —– —–Student Construnctor calledstu1’name:Tomstu2’name:MaryfalseTom’s course: [Java]Mary’s course: [C#]

由结果可知,第一种调用浅拷贝导致对Mary添加课程C#的时候,Tom的课程中竟然也有了C#,而且Mary的课程中也有Tom的Java,且stu1.getCourses()==stu2.getCourses()返回的是“true”,说明二者的course属性指向的就是同一块儿内存;而在第二种情况中,我们为copy出来的Mary的course新开辟了一块儿空间cloning.courses = new Vector(),所以Tom和Mary操控的是不同的Vector内存,两者自然就不一样了。

在上例中,深拷贝deepClone()和浅拷贝newInstance()函数都是我们自己写的,所以deepClone()的Student cloning = (Student) super.clone()和Student cloning = (Strdent) this.clone()都是可行的。除此之外,我们也可以直接覆写本类的clone()函数这样的话就只能使用Student cloning = (Student) super.clone()了,覆写的代码如下:

public Object clone(){//覆写clone(),深拷贝try{Student cloning = (Student) super.clone();cloning.courses = new Vector();//关键点:非基本数据类型的空间需要自己新开辟一块儿return cloning;}catch(CloneNotSupportedException e){e.printStackTrace();}return null;}这里不能使用Student cloning = (Strdent) this.clone()的原因是我们正在覆写本类的clone()方法,如果再调用本类的函数,即:this.clone(),就相当于无线递归无限死循环了,最终肯定会崩溃的。所以这里我们只能调用父类的函数,,即:super.clone()。

每一个成功者都有一个开始。勇于开始,才能找到成功的路。

Java中的clone() 深拷贝 浅拷贝

相关文章:

你感兴趣的文章:

标签云: