【java开发系列】—— 深克隆和浅克隆
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开发系列】—— 深克隆和浅克隆的更多相关文章
- Java中的深克隆和浅克隆
为什么要克隆 首先思考一个问题, 为什么需要克隆对象? 直接new一个对象不行吗? 克隆的对象可能包含一些已经修改过的属性, 而new出来的对象的属性都还是初始化时候的值, 所以当需要一个新的对象来保 ...
- 浅谈Java中的深克隆和浅克隆(阿里面试)
在最近的秋招中,阿里和多益网络都问到了这个问题,虽然很简单,但是我还是想总结一下,感兴趣的可以看一下我的个人博客网站(Spring+MyBatis+redis+nginx+mysql)(适合菜鸟),最 ...
- 【java开发系列】—— JDK安装
前言 作为一个java开发者,安装JDK是不可避免的,但是配置路径却总是记不住,百度也有很多参考例子.这里仅仅当做以后参考的笔记记录. 说到JDK,就不得不提JRE.他们到底是什么呢? 通常我们进行j ...
- Java开发系列-文件上传
概述 Java开发中文件上传的方式有很多,常见的有servlet3.0.common-fileUpload.框架.不管哪种方式,对于文件上传的本质是不变的. 文件上传的准备 文件上传需要客户端跟服务都 ...
- 【java开发系列】—— struts2简单入门示例
前言 最近正好有时间总结一下,过去的知识历程,虽说东西都是入门级的,高手肯定是不屑一顾了,但是对于初次涉猎的小白们,还是可以提供点参考的. struts2其实就是为我们封装了servlet,简化了js ...
- 【java开发系列】—— 自定义注解
之前在开发中,就总纳闷,为什么继承接口时,会出现@Override注解,有时候还会提示写注解@SuppressWarnings? 原来这是java特有的特性,注解! 那么什么是注解呢? 注解就是某种注 ...
- 【java开发系列】—— Tomcat编译报错
由于之前Eclipse里面有一个可移植性的web工程,但是在我很久没用后,再次登录这个IDE的时候就发现了问题. 首先,我的电脑里面有两个版本的JDK,1.6和1.7.两个版本的Tomcat6和7以及 ...
- Java开发系列-JSP
概述 JSP是java 服务器页面,它运行在服务器端,本质上就是一个serlvet,产生的java文件和class保留在tomcat的word目录下. JSP主要作用是将内容的生成与页面相分离. JS ...
- Java开发系列-JDBC
概述 JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和 ...
随机推荐
- Codeforces 1136D Nastya Is Buying Lunch (贪心)
题意: 给一个序列和一组交换序列(a,b),当且仅当a在b的前面(不允许有间隔),这两个数才能交换,问最后一个数最多能移动多少个位置. 分析: 这题是思路是十分的巧妙呀 , 用一个数组num[x] ...
- 正则表达式中模式修正符作用详解(i、g、m、s、x、e)
下面的转:http://www.cnblogs.com/shunyao8210/archive/2008/11/13/1332591.html 总结1:附件参数g的用法 表达式加上参数g之后,表明可以 ...
- [转] Spring Boot实战之Filter实现使用JWT进行接口认证
[From] http://blog.csdn.net/sun_t89/article/details/51923017 Spring Boot实战之Filter实现使用JWT进行接口认证 jwt(j ...
- 安装软件或运行软件时提示缺少api-ms-win-crt-runtime库解决方法
最近碰到一个问题,在我软件安装或运行时会提示缺少api-ms-win-crt-runtime-|1-1-0.dll 当然第一个想到的是运行库没有装,但是很清楚的是我的电脑是装过vc_redist_20 ...
- APP在用户设备发生crash,应该怎么修复
Crash原因 Crash原因有共性,归纳起来有: 内存管理错误 程序逻辑错误 SDK错误 (部署版本< 编译版本) 主线程阻塞 内存管理错误 内存管理是iPhone开发所要掌握的最基本问题, ...
- # 防止xss攻击,过滤script标签,获取出标签外的内容
from bs4 import BeautifulSoups = '<h1>123</h1> <span>456<span>'soup = Beauti ...
- Git~分支真的很轻
轻,让人觉得很爽 所有源代码管理工具都有管理分支的功能,git当然也不例外,而且git的分支是非常轻的,不像tfs,svn那样,复制一大堆代码,git只记录变化的内容,有本地分支与远程分支之分,原则上 ...
- 解决 command not found: express
需要先执行 sudo npm install -g express-generator 再安装 sudo npm install -g express 建立项目骨架 express -e xxx
- TOJ 4393 Game
描述 Bob always plays game with Alice.Today,they are playing a game on a tree.Alice has m1 stones,Bob ...
- git本地创建新分支并推送到远程仓库
1,在当前项目目录,从已有的分支创建新的分支(如从master分支),创建一个dev分支 git checkout -b dev 2,创建完可以查看一下,分支已经切换到dev git branch * ...