文章目录

  • clone
    • 浅克隆和深克隆的区别
    • 浅克隆和深克隆的特点
    • 另一种参考
    • 浅克隆
    • 深克隆
    • 实现
    • 扩展
    • 解决多层克隆问题
    • 总结

clone

浅克隆和深克隆的区别

浅克隆: 对当前对象进行克隆,并克隆该对象所包含的8种基本数据类型和String类型的属性(拷贝一份该对象并重新分配内存,即产生了新的对象)。但如果被克隆的对象中包含除了8种数据类型和String类型外的其他类型的属性,浅克隆并不会克隆这些属性(即不会为这些属性分配内存,而是引用原来对象中的属性)

深克隆: 深克隆是在浅克隆的基础上,递归地克隆除了8种基本类型和String类型之外的属性(即为这些属性重新分配内存而非引用原来对象中的属性)

浅克隆和深克隆的特点

  1. 被克隆的对象的类应实现 Cloneable接口,并重写 clone( )方法
  2. 浅克隆中由于除了8种基本类型和String类型外的其他类型的对象属性不会被克隆,因此当通过新对象对这些属性进行修改时,原对象的属性也会同时改变。深克隆则已经对这些属性重新分配内存,所以当通过新对象对这些属性进行修改时,原对象对属性不会改变。

另一种参考


浅克隆

在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说克隆得到的对象和原型对象的成员变量指向相同的内存地址。

简单来说,在浅克隆中,当对象被复制时,只是复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制。

在Java中,通过覆盖Object类的 clone( )方法可以实现浅克隆

深克隆

在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。

简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。

实现

Java中实现深克隆,可以通过覆盖 Object类的 clone( )方法实现,也可以通过序列化(Serialization)等方式实现

如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆

序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原有对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员变量。因此通过序列化将对象写到一个流中,再从流中将其读出来,可以实现深克隆。需要注意的是能够实现序列化的对象,其类必须实现 Serializable接口,否则无法实现序列化操作。

扩展

Java语言提供的 Cloneable接口和 Serializable接口的代码非常简单,它们都是空接口。这种接口也称为标识接口,标识接口中没有任何方法的定义,其作用是告诉 JRE这些接口的实现类是否具有某个功能,如是否支持克隆、是否支持序列化等。

解决多层克隆问题

如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。

public class Outer implements Serializable{private static final long serialVersionUID = 369285298572941L;  //最好是显式声明IDpublic Inner inner;//Discription:[深度复制方法,需要对象及对象所有的对象属性都实现序列化] public Outer myclone() {Outer outer = null;try {// 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos);oos.writeObject(this);// 将流序列化成对象ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bais);outer = (Outer) ois.readObject();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return outer;}
}

Inner也必须实现Serializable,否则无法序列化:

public class Inner implements Serializable{private static final long serialVersionUID = 872390113109L; //最好是显式声明IDpublic String name = "";public Inner(String name) {this.name = name;}@Overridepublic String toString() {return "Inner的name值为:" + name;}
}

这样也能使两个对象在内存空间内完全独立存在,互不影响对方的值。

总结

实现对象的克隆有两种方式:

  1. 实现Cloneable接口并重写Object类中的clone( )方法;
  2. 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆;

注意:

基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常。这种方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是优于把问题留到运行时。


TODO

Java浅克隆与深克隆-clone相关推荐

  1. Java浅克隆与深克隆区别详解与实现,以及String类型属性克隆为什么不受影响?克隆clone()方法中为什么是super.clone()

    1. 浅克隆实现 public class CloneTest {public static void main(String[] args) throws CloneNotSupportedExce ...

  2. java 浅克隆_(Java)浅克隆与深克隆的区别

    克隆,就是复制一个对象的副本,而克隆又分浅克隆和深克隆.浅克隆是指克隆得到的对象基本类型的值改变了,而源对象的值不会变.但如果被克隆对象引用类型的值改变了,那么源对象的值同样会改变,因为引用类型在栈内 ...

  3. Java浅克隆和深克隆

    浅克隆 在浅克隆中,如果原型对象的成员变量是值类型(int.double.byte.boolean.char等基本数据类型),将数据复制一份给克隆对象:如果原型对象的成员变量是引用类型(类.接口.数组 ...

  4. 【重难点】【Java基础 06】浅克隆与深克隆、Object类的常用方法、util包下的接口

    [重难点][Java基础 06]浅克隆与深克隆.Object对象的常用方法.util包下的接口 文章目录 [重难点][Java基础 06]浅克隆与深克隆.Object对象的常用方法.util包下的接口 ...

  5. Java中的浅克隆与深克隆

    Java中的浅克隆与深克隆 一:前言 二:浅克隆与深克隆的区别 一:前言 克隆,即复制一个对象,该对象的属性与被复制的对象一致,如果不使用Object类中的clone方法实现克隆,可以自己new出一个 ...

  6. 详细分析Java中的浅克隆和深克隆

    本文对浅克隆和深克隆的两种方法(不引入别的开源工具)进行了简单的代码实现(没有内部类语法),对比了浅克隆和深克隆对引用类型的影响,暂不考虑不可变类,确保初学Java者能够看懂并学会,可直接复制源代码进 ...

  7. Java中的深克隆和浅克隆的原理及三种方式实现深克隆

      本文详细介绍了Java中的浅克隆和深克隆的概念,及案例演示如何实现深克隆! 文章目录 1 克隆概述 2 深克隆实现 3 案例 3.1 测试普通clone方法--浅克隆 3.2 使用重写后的clon ...

  8. Java对象克隆——浅克隆和深克隆的区别

    在Java中对象的克隆有深克隆和浅克隆之分.有这种区分的原因是Java中分为基本数据类型和引用数据类型,对于不同的数据类型在内存中的存储的区域是不同的.基本数据类型存储在栈中,引用数据类型存储在堆中. ...

  9. java中浅克隆与深克隆解析

    文章目录 简介 浅克隆 深克隆 嵌套使用clone()方法 序列化方式 浅克隆和深克隆的比较 简介 所谓克隆,就是指依照已存在的数据,复制出一份一样的数据. java中的克隆有浅克隆和深克隆之分,造成 ...

最新文章

  1. 计算机组成 试题,计算机组成典型试题及答案
  2. AI算法起家的今日头条为何败给了色情?一文告诉你机器学习何以搞不定鉴黄
  3. RabbitMQ支持的消息模型
  4. js vue中得延时器_Vue.js实现时分秒倒计时
  5. uva 756—— Biorhythms
  6. blockly自定义中文出问题_[BlocklyNukkit入门]#5自定义物品
  7. 信息学奥赛C++语言:找第一个只出现一次的字符
  8. 解决openfire在使用MySQL数据库后的中文乱码问题(转)
  9. VS2008操作PPT
  10. 设计师效率帮手|提高设计效率的Sketch插件!
  11. MAC代码下统计代码行数工具
  12. tplink迷你路由器中继模式_TP-link迷你无线路由器Repeater模式(中继模式)设置教程(转载).docx...
  13. 用python编程解决鸡兔同笼问题
  14. 夏季养生:一觉,二瓜,三汤,四穴,五果
  15. 2018年度总结(人若无名,专心练剑)
  16. 什么是散列表(Hash Table)
  17. Cent OS 安装 opencv 2.4.4 人脸识别 linux
  18. 网页防篡改技术的前世与今生
  19. DL/T 645多功能电能表通信协议测试方法
  20. wps表格生成html,wps表格如何生成多个文件夹

热门文章

  1. 使用 vs 查看dll 方法
  2. 入门项目·电动车报警器
  3. 推荐 8 个炫酷的 Python 装饰器
  4. 简单的个人主页网站制作
  5. 这么好的扫描仪怎么能不大力推荐呢
  6. RM机器视觉——图像处理、识别装甲板(ROBOMASTER)
  7. 抖音小店无货源是怎么做的?开店需要我们准备什么?经验分享
  8. 分享 2021 豆瓣年度榜单电影/图书
  9. java拆分excel_Java 合并和拆分Word表格中的单元格
  10. 【SQL开发实战技巧】系列(四十五):Oracle12C常用新特性☞VARCHAR2/NVARCHAR2类型最大长度由4000字节扩展到32767字节