【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
复制代码

 

posted @   xingoo  阅读(12920)  评论(0编辑  收藏  举报
编辑推荐:
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
阅读排行:
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee
· 用 DeepSeek 给对象做个网站,她一定感动坏了
· .NET 8.0 + Linux 香橙派,实现高效的 IoT 数据采集与控制解决方案
· .NET中 泛型 + 依赖注入 的实现与应用
历史上的今天:
2013-10-25 VS报错:DEBUG Assertion Failed!
2013-10-25 cuda&vs2010的属性配置
2012-10-25 CListBox
2012-10-25 图m着色问题
点击右上角即可分享
微信分享提示