Java浅拷贝和深拷贝

来源:互联网 发布:网络女主播视频六间房 编辑:程序博客网 时间:2024/06/06 01:31

浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。
深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。

举例来说:
对象A1中包含对B1的引用,B1中包含对C1的引用。
浅拷贝对象A1得到A2,A2 中依然包含对B1的引用,B1中依然包含对C1的引用。
深拷贝则是对浅拷贝的递归,深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2 中包含对C2(C1的copy)的引用。

浅拷贝

class Professor implements Cloneable {    String name;    int age;    Professor(String name, int age) {        this.name = name;        this.age = age;    }    public Object clone() throws CloneNotSupportedException {        return super.clone();    }}class Student implements Cloneable {    String name;    int age;    Professor p;    Student(String name, int age, Professor p) {        this.name = name;        this.age = age;        this.p = p;    }    public Object clone() {        Student o = null;        try {            // 仅仅拷贝对象本身(包括对象中的基本变量)!!!            o = (Student) super.clone();        } catch (CloneNotSupportedException e) {            System.out.println(e.toString());        }        return o;    }}public class ShallowCopy {    public static void main(String[] args) {        Professor p = new Professor("Prof.Chen", 36);        Student s1 = new Student("rookie", 18, p);        System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name                + "," + "\n学生s1教授的年纪" + s1.p.age);        System.out.println("<------------------------>");        Student s2 = (Student) s1.clone();        s2.p.name = "Prof.Yang";        s2.p.age = 30;        s2.name = "newbie";        s2.age = 10;        System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name                + "," + "\n学生s1教授的年纪" + s1.p.age);    }}

运行结果是:
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Chen,
学生s1教授的年纪36
<————————>
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Yang,
学生s1教授的年纪30

我们发现:s2的修改导致了s1的同步变化,这就证明了s1的p和s2的p指向的是同一个对象。这就是”浅拷贝”。
显然”浅拷贝”不能让我们满意。我们再看下”深拷贝”如何实现。

深拷贝

class Professor implements Cloneable {    String name;    int age;    Professor(String name, int age) {        this.name = name;        this.age = age;    }    public Object clone() throws CloneNotSupportedException {        return super.clone();    }}class Student implements Cloneable {    String name;    int age;    Professor p;    Student(String name, int age, Professor p) {        this.name = name;        this.age = age;        this.p = p;    }    public Object clone() {        Student o = null;        try {            // 仅仅拷贝对象本身(包括对象中的基本变量)!!!            o = (Student) super.clone();            // 和ShallowCopy类唯一的变化就是增加了下面这行代码,拷贝对象包含的引用指向的所有对象!!!            o.p = (Professor) p.clone();        } catch (CloneNotSupportedException e) {            System.out.println(e.toString());        }        return o;    }}public class DeepCopy {    public static void main(String[] args) {        Professor p = new Professor("Prof.Chen", 36);        Student s1 = new Student("rookie", 18, p);        System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name                + "," + "\n学生s1教授的年纪" + s1.p.age);        System.out.println("<------------------------>");        Student s2 = (Student) s1.clone();        s2.p.name = "Prof.Yang";        s2.p.age = 30;        s2.name = "newbie";        s2.age = 10;        System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name                + "," + "\n学生s1教授的年纪" + s1.p.age);    }}

运行结果是:
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Chen,
学生s1教授的年纪36
<————————>
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Chen,
学生s1教授的年纪36

我们发现:s2的修改并未导致s1的同步变化,这就是”深拷贝”,不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象!

利用序列化实现深拷贝

深拷贝一个对象,还可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。应当指出的是,写入流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。代码如下:

import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OptionalDataException;import java.io.Serializable;public class DeepCopy implements Serializable {    private static final long serialVersionUID = -1889147729394971115L;    class Professor implements Serializable {        private static final long serialVersionUID = -5461233829245479349L;        String name;        int age;        Professor(String name, int age) {            this.name = name;            this.age = age;        }    }    class Student implements Serializable {        private static final long serialVersionUID = -851210316322914041L;        String name;        int age;        Professor p;        Student(String name, int age, Professor p) {            this.name = name;            this.age = age;            this.p = p;        }        public Object deepClone() throws IOException, OptionalDataException,                ClassNotFoundException {            // 将对象写到流里            ByteArrayOutputStream bo = new ByteArrayOutputStream();            ObjectOutputStream oo = new ObjectOutputStream(bo);            oo.writeObject(this);// object of student            // 从流里读出来            ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());            ObjectInputStream oi = new ObjectInputStream(bi);            return (oi.readObject());        }    }    public static void main(String[] args) {        DeepCopy deepCopy = new DeepCopy();        DeepCopy.Professor p = deepCopy.new Professor("Prof.Chen", 36);        DeepCopy.Student s1 = deepCopy.new Student("rookie", 18, p);        System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name                + "," + "\n学生s1教授的年纪" + s1.p.age);        System.out.println("<------------------------>");        try {            Student s2 = (Student) s1.deepClone();            s2.p.name = "Prof.Yang";            s2.p.age = 30;            s2.name = "newbie";            s2.age = 10;            System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:"                    + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age);        } catch (OptionalDataException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (ClassNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

运行结果是:
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Chen,
学生s1教授的年纪36
<————————>
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Chen,
学生s1教授的年纪36

我们发现:s2的修改并未导致s1的同步变化,利用序列化也可以实现”深拷贝”!

0 0
原创粉丝点击