Java中的深克隆和浅克隆
为什么要克隆
首先思考一个问题, 为什么需要克隆对象? 直接new一个对象不行吗?
克隆的对象可能包含一些已经修改过的属性, 而new出来的对象的属性都还是初始化时候的值, 所以当需要一个新的对象来保存当前对象的"状态"时就要靠克隆了.
当然, 把对象的属性一个一个的赋值给新new的对象也是可以的, 但是这样一来麻烦不说, 二来, 我们通过源码查看 Object的clone方法是一个native方法(native方法是非Java语言实现的代码, 供Java程序调用, 要想访问比较底层的与操作系统相关的就没办法了, 只能由靠近操作系统的语言来实现), 就是快啊, 实在更底层实现的.
我们常见的 Object a = new Object(); Object b; b = a; 这种形式的代码复制的是引用, 即对象在内存中的地址, a和b指向了同一个对象. 而通过clone方法赋值的对象跟原来的对象是同时独立存在的.
概念
浅克隆:
被克隆的对象里的所有变量值都与原来的对象相同, 而所有对其他对象的引用仍然指向原来的对象. 简单说, 浅克隆仅克隆当前对象, 而不克隆当前对象所引用的对象.
深克隆:
被克隆的对象里的所有变量值都与原来的对象相同, 那些引用其他对象的变量将指向被复制过的新对象, 而不再是原来被引用的对象. 简单说, 深克隆不仅克隆了当前对象, 还把当前对象所引用的对象都复制了一遍.
Object中的clone
Object类中的clone()方法属于浅克隆. 它的工作原理如下: 在内存中先开辟一块和原始对象相同的空间, 然后复制原始对象的内容. 对于基本数据类型, 这样操作当然没问题, 但对于引用类型, 由于保存的仅仅是对象的引用, 克隆过去的引用所指向的是同一个对象.
Java中实现浅克隆
java中实现clone要实现 Cloneable 接口, 该接口十分简单, 源码如下:
仅仅起到一个标识的作用.
下面是一个实现浅克隆的例子:
可以看到, 对象确实不是原来的对象了, 但是其中的引用对象却还是原来的对象.
浅克隆对于引用对象仅拷贝引用.
如果一个对象只包含原始数据或者不可变对象域(如: String), 推荐使用浅克隆.
Java中实现深克隆
将类中的所有引用类型都进行clone, 并重写对象clone()方法, 对所有引用类型进行clone.
代码如下:
将所有引用类型都进行clone, 实现了深克隆.
Java序列化克隆
如果引用类型中海包括引用类型, 要实现多层克隆会很麻烦, 这使用可以使用序列化和反序列化的方式实现对象的深克隆.
把对象写到字节流中的过程是序列化的过程, 而把对象从字节流中读出来的过程是反序列化的过程. 由于Java序列化的过程中, 写在流中的是对象的一个拷贝, 而原对象仍然在JVM中, 所以可以利用这个原理来实现对对象的深克隆.
上面代码使用序列化实现如下:
可以将序列化克隆封装为一个方法, 如下所示:
通过该工具类即可进行深度克隆. 要是用该方法, 对象、对象的所有引用类型、引用类型中的引用类型都要实现 Serializable 接口.
当然, 对象中的final对象是不能进行clone的, 因为final的限制.
如果用线程安全的类实现Cloneable, 要保证它的clone方法做好同步工作, 默认的Object.clone方法是没有同步的.
Java中的深克隆和浅克隆的更多相关文章
- 浅谈Java中的深克隆和浅克隆(阿里面试)
在最近的秋招中,阿里和多益网络都问到了这个问题,虽然很简单,但是我还是想总结一下,感兴趣的可以看一下我的个人博客网站(Spring+MyBatis+redis+nginx+mysql)(适合菜鸟),最 ...
- Java克隆--深克隆与浅克隆的区别
克隆,就是复制一个对象的副本,而克隆又分浅克隆和深克隆.浅克隆是指克隆得到的对象基本类型的值改变了,而源对象的值不会变.但如果被克隆对象引用类型的值改变了,那么源对象的值同样会改变,因为引用类型在栈内 ...
- JAVA深复制(深克隆)与浅复制(浅克隆)
1.浅复制与深复制概念⑴浅复制(浅克隆)被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不 复制它所引用的对象. 1. ...
- JAVA深克隆与浅克隆1
复制就是得到一个副本 克隆就是复制一个对象的复本.但一个对象中可能有基本数据类型,如:int,long,float 等,也同时含有非基本数据类型如(数组,集合等)被克隆得到的对象基本类型的值修改 ...
- Java中如何克隆集合——ArrayList和HashSet深拷贝
编程人员经常误用各个集合类提供的拷贝构造函数作为克隆List,Set,ArrayList,HashSet或者其他集合实现的方法.需要记住的是,Java集合的拷贝构造函数只提供浅拷贝而不是深拷贝,这意味 ...
- Java中的深拷贝和浅拷贝
1.浅拷贝与深拷贝概念 (1)浅拷贝(浅克隆) 浅拷贝又叫浅复制,将对象中的所有字段复制到新的对象(副本)中.其中,值类型字段(java中8中原始类型)的值被复制到副本中后,在副本中的修改不会影响到源 ...
- Java中对象的深复制和浅复制详解
1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...
- Java中的深复制与浅复制
1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不 复制它所引用的对象. ...
- 分析java中clone()方法 (转载+修改)
Java中的clone() 方法 java所有的类都是从java.lang.Object类继承而来的,而Object类提供下面的方法对对象进行复制. protected native Object c ...
随机推荐
- eclipse安装及配置pydev
1.首先安装jre,这里记住jre的安装目录,32位操作系统默认安装在“C:\Program Files (x86)\Java\jre1.8.0_91” 2.配置eclipse,这里使用的是压缩包不需 ...
- 弹性盒子模型属性之flex-grow
在学习弹性盒子模型的时候,有几个属性常常让同学们感觉头痛, 不知到最后得到的效果数值到底是怎样计算得来的,那么不要慌,稳住,我们能赢 !!!今天就让我们先来看看flex-grow这个属性 flex-g ...
- Java 多线程开发之 Callable 与线程池
前言 我们常见的创建线程的方式有 2 种:继承 Thread 和 实现 Runnable 接口. 其实,在 JDK 中还提供了另外 2 种 API 让开发者使用. 二.简单介绍 2.1 Callabl ...
- 从 0 开始手写一个 Mybatis 框架,三步搞定!
阅读本文大概需要 3 分钟. MyBatis框架的核心功能其实不难,无非就是动态代理和jdbc的操作,难的是写出来可扩展,高内聚,低耦合的规范的代码. 本文完成的Mybatis功能比较简单,代码还有许 ...
- FastDFS客户端与自定义文件存储系统
<1>安装 安装提供给大家的fdfs_client-py-master.zip到虚拟环境中 pip install fdfs_client-py-master.zip pip instal ...
- 微信小程序消息通知-打卡考勤
微信小程序消息通知-打卡考勤 效果: 稍微改一下js就行,有不必要的错误,我就不改了,哈哈! index.js //index.js const app = getApp() // 填写微信小程序ap ...
- 【Spark调优】聚合操作数据倾斜解决方案
[使用场景] 对RDD执行reduceByKey等聚合类shuffle算子或者在Spark SQL中使用group by语句进行分组聚合时,经过sample或日志.界面定位,发生了数据倾斜. [解决方 ...
- 关于常用的编码工具如何引入jar包
myeclipse和eclipse(差不多)引入jar包: 普通项目: 1.对准你的项目创建一个文件夹名字尽量命名成lib(注意要和src平级,不要在src下创建文件夹). 2.将下载好的依赖放到li ...
- ubuntu默认的Python版本号修改
ubuntu默认的Python是2.7版本的,键入Python3 就可以使用Python3.X版本.下面修改默认的Python版本, 1.删除/usr/bin 下的Python链接 sudo rm / ...
- ES6 块级作用域
作用域包括:全局作用域,函数作用域,块级作用域. 为什么要用块级作用域: 1.内层变量可能会覆盖外层变量. var name = "kevin"; function call() ...