Java中的深拷贝(深复制)和浅拷贝(浅复制)
深拷贝(深复制)和浅拷贝(浅复制)是两个比较通用的概念,尤其在C++语言中,若不弄懂,则会在delete的时候出问题,但是我们在这幸好用的是Java。虽然java自动管理对象的回收,但对于深拷贝(深复制)和浅拷贝(浅复制),我们还是要给予足够的重视,因为有时这两个概念往往会给我们带来不小的困惑。
浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。举例来说更加清楚:对象A1中包含对B1的引用,B1中包含对C1的引用。浅拷贝A1得到A2,A2 中依然包含对B1的引用,B1中依然包含对C1的引用。深拷贝则是对浅拷贝的递归,深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2 中包含对C2(C1的copy)的引用。
若不对clone()方法进行改写,则调用此方法得到的对象即为浅拷贝,下面我们着重谈一下深拷贝。
运行下面的程序,看一看浅拷贝:
class Professor0 implements Cloneable { String name; int age; Professor0(String name, int age) { this .name = name; this .age = age; } public Object clone() throws CloneNotSupportedException { return super .clone(); } } class Student0 implements Cloneable { String name; // 常量对象。 int age; Professor0 p; // 学生1和学生2的引用值都是一样的。 Student0(String name, int age, Professor0 p) { this .name = name; this .age = age; this .p = p; } public Object clone() { Student0 o = null ; try { o = (Student0) super .clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } } public class ShallowCopy { public static void main(String[] args) { Professor0 p = new Professor0( "wangwu" , 50 ); Student0 s1 = new Student0( "zhangsan" , 18 , p); Student0 s2 = (Student0) s1.clone(); s2.p.name = "lisi" ; s2.p.age = 30 ; s2.name = "z" ; s2.age = 45 ; System.out.println( "学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age); // 学生1的教授 } } |
s2变了,但s1也变了,证明s1的p和s2的p指向的是同一个对象。这在我们有的实际需求中,却不是这样,因而我们需要深拷贝:
class Professor implements Cloneable { String name; int age; Professor(String name, int age) { this .name = name; this .age = age; } public Object clone() { Object o = null ; try { o = super .clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } } class Student implements Cloneable { String name; int age; Professor p; Student(String name, int age, Professor p) { this .name = name; this .age = age; this .p = p; } public Object clone() { Student o = null ; try { o = (Student) super .clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } o.p = (Professor) p.clone(); return o; } } public class DeepCopy { public static void main(String args[]) { long t1 = System.currentTimeMillis(); Professor p = new Professor( "wangwu" , 50 ); Student s1 = new Student( "zhangsan" , 18 , p); Student s2 = (Student) s1.clone(); s2.p.name = "lisi" ; s2.p.age = 30 ; System.out.println( "name=" + s1.p.name + "," + "age=" + s1.p.age); // 学生1的教授不改变。 long t2 = System.currentTimeMillis(); System.out.println(t2-t1); } } |
当然我们还有一种深拷贝方法,就是将对象串行化:
import java.io.*; //Serialization is time-consuming class Professor2 implements Serializable { /** * */ private static final long serialVersionUID = 1L; String name; int age; Professor2(String name, int age) { this .name = name; this .age = age; } } class Student2 implements Serializable { /** * */ private static final long serialVersionUID = 1L; String name; // 常量对象。 int age; Professor2 p; // 学生1和学生2的引用值都是一样的。 Student2(String name, int age, Professor2 p) { this .name = name; this .age = age; this .p = p; } public Object deepClone() throws IOException, OptionalDataException, ClassNotFoundException { // 将对象写到流里 ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo = new ObjectOutputStream(bo); oo.writeObject( this ); // 从流里读出来 ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi = new ObjectInputStream(bi); return (oi.readObject()); } } public class DeepCopy2 { /** * @param args */ public static void main(String[] args) throws OptionalDataException, IOException, ClassNotFoundException { long t1 = System.currentTimeMillis(); Professor2 p = new Professor2( "wangwu" , 50 ); Student2 s1 = new Student2( "zhangsan" , 18 , p); Student2 s2 = (Student2) s1.deepClone(); s2.p.name = "lisi" ; s2.p.age = 30 ; System.out.println( "name=" + s1.p.name + "," + "age=" + s1.p.age); // 学生1的教授不改变。 long t2 = System.currentTimeMillis(); System.out.println(t2-t1); } } |
但是串行化却很耗时,在一些框架中,我们便可以感受到,它们往往将对象进行串行化后进行传递,耗时较多。
Java中的深拷贝(深复制)和浅拷贝(浅复制)的更多相关文章
- Java中的深拷贝和浅拷贝(转载)
深拷贝(深复制)和浅拷贝(浅复制)是两个比较通用的概念,尤其在C++语言中,若不弄懂,则会在delete的时候出问题,但是我们在这幸好用的是Java.虽然java自动管理对象的回收,但对于深拷贝(深复 ...
- Java中的深拷贝和浅拷贝
1.浅拷贝与深拷贝概念 (1)浅拷贝(浅克隆) 浅拷贝又叫浅复制,将对象中的所有字段复制到新的对象(副本)中.其中,值类型字段(java中8中原始类型)的值被复制到副本中后,在副本中的修改不会影响到源 ...
- 浅谈Java中的深拷贝和浅拷贝(转载)
浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...
- 浅谈Java中的深拷贝和浅拷贝
转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...
- 内功心法 -- Java中的深拷贝和浅拷贝
写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------这篇博客主要来谈谈" ...
- Java中对象的深复制和浅复制详解
1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...
- Java中的clone()----深复制,浅复制
这篇文章主要介绍了Java中对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下 1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他 ...
- java基础(十七)----- 浅谈Java中的深拷贝和浅拷贝 —— 面试必问
假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...
- 浅析Java中的深拷贝和浅拷
浅析Java中的深拷贝和浅拷贝 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: in ...
随机推荐
- 001-ant design pro安装、目录结构、项目加载启动【原始、以及idea开发】
一.概述 1.1.脚手架概念 编程领域中的“脚手架(Scaffolding)”指的是能够快速搭建项目“骨架”的一类工具.例如大多数的React项目都有src,public,webpack配置文件等等, ...
- Dora.Interception, 为.NET Core度身打造的AOP框架:不一样的Interceptor定义方式
相较于社区其他主流的AOP框架,Dora.Interception在Interceptor提供了完全不同的编程方式.我们并没有为Interceptor定义一个接口,正是因为不需要实现一个预定义的接口, ...
- MySQL之存储引擎(Day39)
一 什么是存储引擎 mysql中建立的库=====>文件夹 库中建立的表=====>文件 现实生活中我们用来存储数据的文件应该有不同的类型:比如存文本用txt类型,存表格用excel,存图 ...
- yum速查
yum命令是在Fedora和RedHat以及SUSE中基于rpm的软件包管理器,它可以使系统管理人员交互和自动化地更细与管理RPM软件包, 能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖 ...
- redis 笔记04 服务器、复制
服务器 1. 一个命令请求从发送到完成主要包括以下步骤: 1). 客户端将命令请求发送给服务器 2). 服务器读取命令请求,并分析出命令参数 3). 命令执行器根据参数查找命令的实现函数,然后执行实现 ...
- js防抖
那我们设置个 options 作为第三个参数,然后根据传的值判断到底哪种效果,我们约定: leading:false 表示禁用第一次执行trailing: false 表示禁用停止触发的回调 我们来改 ...
- FTP 服务器性能 测试点
测试FTP 服务器性能测试点: 1. ftp软件性能 2. ftp服务器硬件处理性能(IO/CPU/ROM) 3. ftp服务器网络吞吐性能 (NET IO) 有针对性的测试 达到的效果会比较好. 建 ...
- Json日期格式 转化为 YYYY-MM-DD-hh-mm-ss
function timeStamp2String(time) { var datetime = new Date(); datetime.setTime(time); var year = date ...
- Centos 6\7 防火墙入门配置
Centos 6 -- iptables iptables 用法: iptables (选项) (参数) 选项: -t<表>:指定要操纵的表: -A:向规则链中添加条目: -D:从规则链中 ...
- ubuntu 致命错误: zlib.h:没有那个文件或目录【转】
本文转载自:https://blog.csdn.net/u013359794/article/details/44922685?locationnum=15&fps=1 编译时,出现错误,提示 ...