关于Java对象深浅拷贝的理解

笔者在研究spring原型模式的时候发现自身对java深浅拷贝的理解存在问题,特此写下这篇随笔
以下为笔者对java深浅拷贝的理解 如有不对请指正
java复制采用的是由底层为C语言编写的native的方法 clone()完成,而深浅克隆都是基于clone方法实现的,而object 对象的clone 方法默认是基于浅拷贝的
一.注:基础数据类型+引用数据类型String 深浅拷贝都是一样的,基础数据类型基于值传递,应用数据类型String 由于每次修改值都会修改都会在堆中重新开辟空间复制并替换原来引用故 深浅拷贝出来的对象 源对象值无论怎么修改都不会影响到克隆对象
1.对于其他自定义对象和java自带的引用对象 浅拷贝和深拷贝是存在区别的
1.1 浅拷贝:会复制原引用对象类型的引用给复制对象 所以 复制对象引用对象的值发生变化,源对象的响应字段的值也会发生变化
1.2 深拷贝:则是复制值并生成的引用给复制对象所以源对象字段值发生变化不会影响到克隆对象

二,关于深拷贝的实现方式
2.1 对于并不复杂的单个应用链,可以采取重写克隆方法,并调用单个引用对象的clone方法来实现
在这里插入图片描述
2.2 而对于过于复制的调用链,可以用反射和序列化解决,但笔者更建议使用序列化,(反射的性能比较令人担忧)具体实现方式为复制对象,和其引用的对象都实现序列化接口 重写克隆对象的clone()方法实现深度克隆

//深度拷贝
public Object clone() throws Exception{
    // 序列化
    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();
}

以上为笔者对深浅克隆的理解最后贴出其他解答以便读者理解对比

1.浅拷贝(Shallow Copy):①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。
1.2 浅拷贝的特点
(1) 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个。
(2) 对于引用类型,比如数组或者类对象,因为引用类型是引用传递,所以浅拷贝只是把内存地址赋值给了成员变量,它们指向了同一内存空间。改变其中一个,会对另外一个也产生影响。
在这里插入图片描述

2.深拷贝:首先介绍对象图的概念。设想一下,一个类有一个对象,其成员变量中又有一个对象,该对象指向另一个对象,另一个对象又指向另一个对象,直到一个确定的实例。这就形成了对象图。那么,对于深拷贝来说,不仅要复制对象的所有基本数据类型的成员变量值,还要为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象图进行拷贝!
简单地说,深拷贝对引用数据类型的成员变量的对象图中所有的对象都开辟了内存空间;而浅拷贝只是传递地址指向,新的对象并没有对引用数据类型创建内存空间。

2.1深拷贝的特点:
(1) 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个(和浅拷贝一样)。
(2) 对于引用类型,比如数组或者类对象,深拷贝会新建一个对象空间,然后拷贝里面的内容,所以它们指向了不同的内存空间。改变其中一个,不会对另外一个也产生影响。
(3) 对于有多层对象的,每个对象都需要实现 Cloneable 并重写 clone() 方法,进而实现了对象的串行层层拷贝。
(4) 深拷贝相比于浅拷贝速度较慢并且花销较大。
在这里插入图片描述
注:图片转载自网站 深浅克隆具体代码实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值