zoukankan      html  css  js  c++  java
  • 深拷贝和浅拷贝

    • 浅拷贝:只拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。

    或者说,被复制对象的所有变量都含有与原来的对象相同的值,对象的引用对象会在原来的对象和它的副本之间共享。 调用clone()得到的对象。

    • 深拷贝:不仅拷贝对象本身,而且拷贝对象包含引用指向的所有对象。    

    简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍。即对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容。override clone()得到的对象,

    对其内的引用类型的变量,再进行一次 clone()。或者使用序列化。


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

    范例:浅拷贝
    1.实体类 - Professor0

     1 public class Professor0 implements Cloneable {
     2 
     3     public String name;
     4     
     5     public int age;
     6 
     7     public Professor0(String name, int age) {
     8         this.name = name;
     9         this.age = age;
    10     }
    11     
    12     public Object clone() throws CloneNotSupportedException {
    13         return super.clone();
    14     }
    15     
    16     
    17 
    18 }


    2.实体类 - Student0

     1 public class Student0 implements Cloneable {
     2 
     3     public String name;
     4     public int age;
     5     public Professor0 p;
     6     public Student0(String name, int age, Professor0 p) {
     7         this.name = name;
     8         this.age = age;
     9         this.p = p;
    10     }
    11     
    12     public Object clone() {
    13         Student0 o = null;
    14         try {
    15             o = (Student0) super.clone();
    16         } catch (CloneNotSupportedException e) {
    17             System.out.println(e.toString());
    18         }
    19         return o;
    20     }
    21     
    22     
    23     
    24     
    25 }


    3.浅拷贝类 - ShallowCopy

     1 public class ShallowCopy {
     2 
     3     public static void main(String[] args) {
     4         Professor0 p = new Professor0("张三", 50);
     5         Student0 s1 = new Student0("李四", 18, p);
     6         Student0 s2 = (Student0) s1.clone();
     7         s2.p.name = "王五";
     8         s2.p.age = 30;
     9         s2.name = "赵六";
    10         s2.age = 45;
    11         System.out.println("学生s1的姓名:" + s1.name + "
    学生s1教授的姓名:" + s1.p.name + ",
    学生s1教授的年龄:" + s1.p.age);
    12     }
    13     
    14 }

    结果:    学生s1的姓名:李四
            学生s1教授的姓名:王五,
            学生s1教授的年龄:30
            
    总结:s2.p变了,s1.p也变了,证明s1的p和s2的p指向的是同一个对象

    范例:深拷贝
    1.实体类 - Professor

     1 public class Professor implements Cloneable {
     2 
     3     public String name;
     4     
     5     public int age;
     6 
     7     public Professor(String name, int age) {
     8         this.name = name;
     9         this.age = age;
    10     }
    11     
    12     public Object clone(){
    13         Object o = null;
    14         try {
    15             o = super.clone();
    16         } catch (CloneNotSupportedException e) {
    17             System.out.println(e.toString());
    18         }
    19         return o;
    20     }
    21     
    22     
    23 
    24 }


    2.实体类 - Student

     1 public class Student implements Cloneable {
     2 
     3     public String name;
     4     public int age;
     5     public Professor p;
     6     public Student(String name, int age, Professor p) {
     7         this.name = name;
     8         this.age = age;
     9         this.p = p;
    10     }
    11     
    12     public Object clone() {
    13         Student o = null;
    14         try {
    15             o = (Student) super.clone();
    16         } catch (CloneNotSupportedException e) {
    17             System.out.println(e.toString());
    18         }
    19         o.p = (Professor) p.clone();
    20         return o;
    21     }
    22     
    23     
    24     
    25     
    26 }


    3.深拷贝类 - DeepCopy

     1 public class DeepCopy {
     2 
     3     public static void main(String[] args) {
     4         
     5         long t1 = System.currentTimeMillis();
     6         Professor p = new Professor("张三", 50);
     7         Student s1 = new Student("李四", 18, p);
     8         Student s2 = (Student) s1.clone();
     9         s2.p.name = "王五";
    10         s2.p.age = 30;
    11         System.out.println("学生s1的姓名:" + s1.name + "
    学生s1教授的姓名:" + s1.p.name + ",
    学生s1教授的年龄:" + s1.p.age);
    12         long t2 = System.currentTimeMillis();
    13         System.out.println(t2-t1);
    14     }
    15     
    16 }

    结果:    学生s1的姓名:李四
            学生s1教授的姓名:张三,
            学生s1教授的年龄:50
            1

    总结:s2.p变了,s1.p没变。证明s1的p和s2的p指向的不是同一个对象

    范例:采用序列化实现深拷贝
    1.实体类 - Professor2

     1 public class Professor2 implements Serializable {
     2     private static final long serialVersionUID = 1L;
     3 
     4     public String name;
     5     
     6     public int age;
     7 
     8     public Professor2(String name, int age) {
     9         this.name = name;
    10         this.age = age;
    11     }
    12     
    13 
    14 }


    2.实体类 - Student2

     1 public class Student2 implements Serializable {
     2     private static final long serialVersionUID = 1L;
     3     public String name;
     4     public int age;
     5     public Professor2 p;
     6     
     7     public Student2(String name, int age, Professor2 p) {
     8         this.name = name;
     9         this.age = age;
    10         this.p = p;
    11     }
    12     
    13     public Object deepClone() throws IOException, ClassNotFoundException {
    14 //        将对象写到流里
    15         ByteArrayOutputStream bo = new ByteArrayOutputStream();
    16         ObjectOutputStream oo = new ObjectOutputStream(bo);
    17         oo.writeObject(this);
    18 //        从流里读出来
    19         ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
    20         ObjectInputStream oi = new ObjectInputStream(bi);
    21         return oi.readObject();
    22         
    23     }
    24     
    25 }


    3.深拷贝类 - DeepCopy2

     1 public class DeepCopy2 {
     2 
     3     public static void main(String[] args) throws ClassNotFoundException, IOException {
     4         
     5         long t1 = System.currentTimeMillis();
     6         Professor2 p = new Professor2("张三", 50);
     7         Student2 s1 = new Student2("李四", 18, p);
     8         Student2 s2 = (Student2) s1.deepClone();
     9         s2.p.name = "王五";
    10         s2.p.age = 30;
    11         System.out.println("学生s1的姓名:" + s1.name + "
    学生s1教授的姓名:" + s1.p.name + ",
    学生s1教授的年龄:" + s1.p.age);
    12         long t2 = System.currentTimeMillis();
    13         System.out.println(t2-t1);
    14     }
    15     
    16 }

    结果:    学生s1的姓名:李四
            学生s1教授的姓名:张三,
            学生s1教授的年龄:50
            85

    总结:s2.p变了,s1.p没变。证明s1的p和s2的p指向的不是同一个对象。相比实现Cloneable,实现Serializable更耗时。


  • 相关阅读:
    chmod命令
    ls命令
    数组值去重-小技巧
    使用redis接管session
    使用redis接管cookie
    redis操作封装类
    HTTP协议详解
    Linux网络编程--多播
    Live555 分析(三):客服端
    Live555 分析(二):服务端
  • 原文地址:https://www.cnblogs.com/ivy-xu/p/5752461.html
Copyright © 2011-2022 走看看