zoukankan      html  css  js  c++  java
  • 【java开发系列】—— 深克隆和浅克隆

      Java支持我们对一个对象进行克隆,通常用在装饰模式和原型模式中。那么什么是深克隆,什么是浅克隆呢。

      【浅克隆】,通常只是对克隆的实例进行复制,但里面的其他子对象,都是共用的。

      【深克隆】,克隆的时候会复制它的子对象的引用,里面所有的变量和子对象都是又额外拷贝了一份。

      下面的两个例子可以很好的说明他们的区别:

      首先看一下类图

      Husband类有一个对wife的引用,当进行浅克隆的时,wife变量都会指向同一个Wife;而进行深克隆时,会指向不同的Wife。下面进行一下验证:

      【浅克隆】

     1 public Object clone() {
     2         Husband husband = null;
     3         try{
     4             husband = (Husband)super.clone();
     5         }catch(CloneNotSupportedException e){
     6             e.printStackTrace();
     7         }finally{
     8             return husband;
     9         }
    10     }

      【深克隆】

     1 public Object deepClone() throws IOException,ClassNotFoundException {
     2         //将对象写到流里
     3         ByteArrayOutputStream bos = new ByteArrayOutputStream();
     4         ObjectOutputStream oos = new ObjectOutputStream(bos);
     5         oos.writeObject(this);
     6         //从流里读回来
     7         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
     8         ObjectInputStream ois = new ObjectInputStream(bis);
     9         return ois.readObject();
    10     }

      【全部代码】

      1 package com.xingoo.clone;
      2 
      3 import java.io.ByteArrayInputStream;
      4 import java.io.ByteArrayOutputStream;
      5 import java.io.IOException;
      6 import java.io.ObjectInputStream;
      7 import java.io.ObjectOutputStream;
      8 import java.io.Serializable;
      9 import java.util.Date;
     10 
     11 class Wife implements Serializable{
     12     private String name;
     13     private Date birthday;
     14     
     15     public Wife(){
     16         name = "芙蓉姐姐";
     17         birthday = new Date();
     18     }
     19     public Date getBirthday(){
     20         return birthday;
     21     }
     22     
     23     public String getName() {
     24         return name;
     25     }
     26     public void setName(String name) {
     27         this.name = name;
     28     }
     29 }
     30 class Husband implements Cloneable,Serializable{
     31     private Wife wife;
     32     private Date birthday;
     33     
     34     public Husband(){
     35         wife = new Wife();
     36         birthday = new Date();
     37     }
     38     
     39     public Wife getWife(){
     40         return wife;
     41     }
     42     
     43     public Date getBirthday(){
     44         return birthday;
     45     }
     46     /**
     47      * 浅克隆一个对象
     48      */
     49     public Object clone() {
     50         Husband husband = null;
     51         try{
     52             husband = (Husband)super.clone();
     53         }catch(CloneNotSupportedException e){
     54             e.printStackTrace();
     55         }finally{
     56             return husband;
     57         }
     58     }
     59     /**
     60      * 利用串行化深克隆一个对象,把对象以及它的引用读到流里,在写入其他的对象
     61      * @return
     62      * @throws IOException
     63      * @throws ClassNotFoundException
     64      */
     65     public Object deepClone() throws IOException,ClassNotFoundException {
     66         //将对象写到流里
     67         ByteArrayOutputStream bos = new ByteArrayOutputStream();
     68         ObjectOutputStream oos = new ObjectOutputStream(bos);
     69         oos.writeObject(this);
     70         //从流里读回来
     71         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
     72         ObjectInputStream ois = new ObjectInputStream(bis);
     73         return ois.readObject();
     74     }
     75 }
     76 public class Test {
     77     public static void main(String[] args){
     78         try{
     79             Husband husband = new Husband();
     80             System.out.println("husband birthday "+husband.getBirthday().getTime());
     81             System.out.println("wife birthday "+husband.getWife().getBirthday().getTime());
     82             System.out.println();
     83             Husband husband1 = (Husband)husband.clone();
     84             System.out.println("husband1 birthday "+husband1.getBirthday().getTime());
     85             System.out.println("wife birthday "+husband1.getWife().getBirthday().getTime());
     86             System.out.println();
     87             System.out.println("是否是同一个husband "+(husband == husband1));
     88             System.out.println("是否是同一个wife "+ (husband.getWife() == husband1.getWife()));
     89             System.out.println();
     90             Husband husband2 = (Husband)husband.deepClone();
     91             System.out.println("husband2 birthday "+husband2.getBirthday().getTime());
     92             System.out.println("wife birthday "+husband2.getWife().getBirthday().getTime());
     93             System.out.println();
     94             System.out.println("是否是同一个husband "+(husband == husband2));
     95             System.out.println("是否是同一个wife "+ (husband.getWife() == husband2.getWife()));
     96         }catch(Exception e){
     97             e.printStackTrace();
     98         }
     99     }
    100 }

      【运行结果】

    husband birthday 1414247244668
    wife birthday 1414247244668
    
    husband1 birthday 1414247244668
    wife birthday 1414247244668
    是否是同一个husband false
    是否是同一个wife true
    
    husband2 birthday 1414247244668
    wife birthday 1414247244668
    是否是同一个husband false
    是否是同一个wife false
  • 相关阅读:
    在ubuntu 12.04 中配置java环境(安装jdk, tomcat, maven, eclipse)
    java 对EXCEL表格的处理
    JAVA下载文件中文乱码问题
    Java 判断文件夹、文件是否存在、否则创建文件夹
    jspSmartUpload上传下载全攻略
    intellJ实用技巧
    main 方法,
    老师,有没有类似微信布局的好的开源库?
    Android 日常开发总结的技术经验 60 条
    新的android studio创建的fragment工程跟老师讲的结构有区别
  • 原文地址:https://www.cnblogs.com/xing901022/p/4051097.html
Copyright © 2011-2022 走看看