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

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

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

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

  首先看一下类图

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

  【浅克隆】

 public Object clone() {
Husband husband = null;
try{
husband = (Husband)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}finally{
return husband;
}
}

  【深克隆】

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

  【全部代码】

 package com.xingoo.clone;

 import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date; class Wife implements Serializable{
private String name;
private Date birthday; public Wife(){
name = "芙蓉姐姐";
birthday = new Date();
}
public Date getBirthday(){
return birthday;
} public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Husband implements Cloneable,Serializable{
private Wife wife;
private Date birthday; public Husband(){
wife = new Wife();
birthday = new Date();
} public Wife getWife(){
return wife;
} public Date getBirthday(){
return birthday;
}
/**
* 浅克隆一个对象
*/
public Object clone() {
Husband husband = null;
try{
husband = (Husband)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}finally{
return husband;
}
}
/**
* 利用串行化深克隆一个对象,把对象以及它的引用读到流里,在写入其他的对象
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public Object deepClone() throws IOException,ClassNotFoundException {
//将对象写到流里
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//从流里读回来
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
public class Test {
public static void main(String[] args){
try{
Husband husband = new Husband();
System.out.println("husband birthday "+husband.getBirthday().getTime());
System.out.println("wife birthday "+husband.getWife().getBirthday().getTime());
System.out.println();
Husband husband1 = (Husband)husband.clone();
System.out.println("husband1 birthday "+husband1.getBirthday().getTime());
System.out.println("wife birthday "+husband1.getWife().getBirthday().getTime());
System.out.println();
System.out.println("是否是同一个husband "+(husband == husband1));
System.out.println("是否是同一个wife "+ (husband.getWife() == husband1.getWife()));
System.out.println();
Husband husband2 = (Husband)husband.deepClone();
System.out.println("husband2 birthday "+husband2.getBirthday().getTime());
System.out.println("wife birthday "+husband2.getWife().getBirthday().getTime());
System.out.println();
System.out.println("是否是同一个husband "+(husband == husband2));
System.out.println("是否是同一个wife "+ (husband.getWife() == husband2.getWife()));
}catch(Exception e){
e.printStackTrace();
}
}
}

  【运行结果】

husband birthday
wife birthday husband1 birthday
wife birthday
是否是同一个husband false
是否是同一个wife true husband2 birthday
wife birthday
是否是同一个husband false
是否是同一个wife false

【java开发系列】—— 深克隆和浅克隆的更多相关文章

  1. Java中的深克隆和浅克隆

    为什么要克隆 首先思考一个问题, 为什么需要克隆对象? 直接new一个对象不行吗? 克隆的对象可能包含一些已经修改过的属性, 而new出来的对象的属性都还是初始化时候的值, 所以当需要一个新的对象来保 ...

  2. 浅谈Java中的深克隆和浅克隆(阿里面试)

    在最近的秋招中,阿里和多益网络都问到了这个问题,虽然很简单,但是我还是想总结一下,感兴趣的可以看一下我的个人博客网站(Spring+MyBatis+redis+nginx+mysql)(适合菜鸟),最 ...

  3. 【java开发系列】—— JDK安装

    前言 作为一个java开发者,安装JDK是不可避免的,但是配置路径却总是记不住,百度也有很多参考例子.这里仅仅当做以后参考的笔记记录. 说到JDK,就不得不提JRE.他们到底是什么呢? 通常我们进行j ...

  4. Java开发系列-文件上传

    概述 Java开发中文件上传的方式有很多,常见的有servlet3.0.common-fileUpload.框架.不管哪种方式,对于文件上传的本质是不变的. 文件上传的准备 文件上传需要客户端跟服务都 ...

  5. 【java开发系列】—— struts2简单入门示例

    前言 最近正好有时间总结一下,过去的知识历程,虽说东西都是入门级的,高手肯定是不屑一顾了,但是对于初次涉猎的小白们,还是可以提供点参考的. struts2其实就是为我们封装了servlet,简化了js ...

  6. 【java开发系列】—— 自定义注解

    之前在开发中,就总纳闷,为什么继承接口时,会出现@Override注解,有时候还会提示写注解@SuppressWarnings? 原来这是java特有的特性,注解! 那么什么是注解呢? 注解就是某种注 ...

  7. 【java开发系列】—— Tomcat编译报错

    由于之前Eclipse里面有一个可移植性的web工程,但是在我很久没用后,再次登录这个IDE的时候就发现了问题. 首先,我的电脑里面有两个版本的JDK,1.6和1.7.两个版本的Tomcat6和7以及 ...

  8. Java开发系列-JSP

    概述 JSP是java 服务器页面,它运行在服务器端,本质上就是一个serlvet,产生的java文件和class保留在tomcat的word目录下. JSP主要作用是将内容的生成与页面相分离. JS ...

  9. Java开发系列-JDBC

    概述 JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和 ...

随机推荐

  1. Oracle之UTL_FILE 包用法详解

    [转自] http://zhangzhongjie.iteye.com/blog/1903024 UTL_FILE包可以用来读写操作系统上的文本文件,UTL_FILE提供了在客户端(FORM等等)和服 ...

  2. Oracle列转行函数Listagg以及pivot查询示例

    简单的Oracle列转行函数Listagg示例: CREATE TABLE tbl_test (catalog VARCHAR(1),product VARCHAR(2),amount NUMBER) ...

  3. requests模块的一些总结

    一.cookie模拟登录的三种方式 #!/usr/bin/env python # -*- coding: utf-8 -*- #author tom import requests post_url ...

  4. scrapy框架初识

    一.scrapy简介 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍.所谓的框架就是一个已经被集成了各种功能(高性能异步下载,队列,分布式,解析,持久化等)的具 ...

  5. Scrapy错误-no active project Unknown command: crawl

    在运行别人的scrapy项目时,使用命令行 scrapy crawl douban(douban是该项目里爬虫的名字,烂大街的小项目---抓取豆瓣电影). 执行之后,出现报错如下: 上网搜寻无果. 大 ...

  6. CSS2.1

    学而时习之,不亦说乎!                              --<论语> CSS:cascading style sheet(层叠样式表) 作用:描述页面的样式. 书 ...

  7. aoj0121

    一.题意:类似于华容道,输入是8个数字,输入虽然是一行,但实际是以两行的方式操作的.0表示空位,别的相邻数字可移动到该位置上.求最少移动步骤得到指定的状态. 二.思路:这题可以用BFS来解决.因为在每 ...

  8. C#数组 动态添加元素

    string[] a = new string[] { "1", "2", "3" }; 给a追加一个 "4" 1 2 ...

  9. web app与app的区别,即html5与app的区别

    公司准备要做一个项目,是p2p配资的app.在网上问了一些人后,发现有的是直接有html5做好后,用软件封装的.之前我学过app的开发,当时Android版本的,知道开发Android app时写的代 ...

  10. Rsa2加密报错java.security.spec.InvalidKeySpecException的解决办法

    最近在和支付宝支付做个对接,Java项目中用到了RSA2进行加解密,在加密过程中遇到了错误: java.security.spec.InvalidKeySpecException: java.secu ...