java数组深拷贝和浅拷贝_java中的深拷贝与浅拷贝(值类型 vs 引用类型)

对象赋值

赋值是日常编程过程中最常见的操作,最简单的比如:

Student codeSheep = new Student(); Student codePig = codeSheep;

严格来说,这种不能算是对象拷贝,因为拷贝的仅仅只是引用关系,并没有生成新的实际对象:

47883fc65f165f6244e03f62cf7ca555.png

浅拷贝

浅拷贝属于对象克隆方式的一种,重要的特性体现在这个 「浅」 字上。

比如我们试图通过studen1实例,拷贝得到student2,如果是浅拷贝这种方式,大致模型可以示意成如下所示的样子:

3113480260b1a89db144439bab058364.png

很明显,值类型的字段会复制一份,而引用类型的字段拷贝的仅仅是引用地址,而该引用地址指向的实际对象空间其实只有一份。

深拷贝

深拷贝相较于上面所示的浅拷贝,除了值类型字段会复制一份,引用类型字段所指向的对象,会在内存中也创建一个副本

4bcb1e54030a69c84b3546162cfb4d41.png

浅拷贝代码实现

还以上文的例子来讲,我想通过student1拷贝得到student2,浅拷贝的典型实现方式是:让被复制对象的类实现Cloneable接口,并重写clone()方法即可。

以上面的Student类拷贝为例:

public class Student implements Cloneable { private String name; // 姓名 private int age; // 年龄 private Major major; // 所学专业 @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } // ... 其他省略 ... }

public class Test { public static void main(String[] args) throws CloneNotSupportedException { Major m = new Major("计算机科学与技术",666666); Student student1 = new Student( "CodeSheep", 18, m ); // 由 student1 拷贝得到 student2 Student student2 = (Student) student1.clone(); System.out.println( student1 == student2 ); System.out.println( student1 ); System.out.println( student2 ); System.out.println( "\n" ); // 修改student1的值类型字段 student1.setAge( 35 ); // 修改student1的引用类型字段 m.setMajorName( "电子信息工程" ); m.setMajorId( 888888 ); System.out.println( student1 ); System.out.println( student2 ); } }

运行结果:

7259725d3595374897198628f479f489.png

从结果可以看出:

student1==student2打印false,说明clone()方法的确克隆出了一个新对象;

修改值类型字段并不影响克隆出来的新对象,符合预期;

而修改了student1内部的引用对象,克隆对象student2也受到了波及,说明内部还是关联在一起的

深拷贝代码实现

深度遍历式拷贝

虽然clone()方法可以完成对象的拷贝工作,但是注意:clone()方法默认是浅拷贝行为,就像上面的例子一样。若想实现深拷贝需覆写 clone()方法实现引用对象的深度遍历式拷贝,进行地毯式搜索。

所以对于上面的例子,如果想实现深拷贝,首先需要对更深一层次的引用类Major做改造,让其也实现Cloneable接口并重写clone()方法:

public class Major implements Cloneable { @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } // ... 其他省略 ... }

其次我们还需要在顶层的调用类中重写clone方法,来调用引用类型字段的clone()方法实现深度拷贝,对应到本文那就是Student类:

public class Student implements Cloneable { @Override public Object clone() throws CloneNotSupportedException { Student student = (Student) super.clone(); student.major = (Major) major.clone(); // 重要!!! return student; } // ... 其他省略 ... }

这时候上面的测试用例不变,运行可得结果:

10ab389d5758108f65f4deaef089507a.png

391e023c9082fe6326f11da13b87d4ff.png

很明显,这时候student1和student2两个对象就完全独立了,不受互相的干扰。

利用反序列化实现深拷贝

利用反序列化技术,我们也可以从一个对象深拷贝出另一个复制对象,而且在解决多层套娃式的深拷贝问题时效果出奇的好。

所以我们这里改造一下Student类,让其clone()方法通过序列化和反序列化的方式来生成一个原对象的深拷贝副本:

public class Student implements Serializable { private String name; // 姓名 private int age; // 年龄 private Major major; // 所学专业 public Student clone() { try { // 将对象本身序列化到字节流 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream( byteArrayOutputStream ); objectOutputStream.writeObject( this ); // 再将字节流通过反序列化方式得到对象副本 ObjectInputStream objectInputStream = new ObjectInputStream( new ByteArrayInputStream( byteArrayOutputStream.toByteArray() ) ); return (Student) objectInputStream.readObject(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } // ... 其他省略 ... }

当然这种情况下要求被引用的子类(比如这里的Major类)也必须是可以序列化的,即实现了Serializable接口:

public class Major implements Serializable { // ... 其他省略 ... }

这时候测试用例完全不变,直接运行,也可以得到如下结果:

7cd2a1c4ac24c1b0b714c91705aaec45.png

75dd2b538f2640af6dce6cc15e5c189d.png

很明显,这时候student1和student2两个对象也是完全独立的,不受互相的干扰,深拷贝完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/296486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

各大厂抢招WPF,小米这回是下了血本啊...

九银十进入尾声,小米又爆出高薪岗位:35k左右,14薪,招5年左右.NET,要求WPF和自动化( 职位:https://app.mokahr.com/apply/xiaomi/287/#/job/523278c0-c504-4cdc-bb88-28c1b101ac76)。今年招WPF的大厂太多了&…

你永远都不知道你老公可以多幼稚......

1 爸爸带女儿!两个幼稚鬼▼2 常州一小区提醒防疫四种语言切换无压力▼3 我知道了!他的门牙肯定有条缝▼4 狗子OS:今天栏杆和木棍必须要断一个▼5 掀起你的假发来让我帮你擦擦汗▼6 干啥啥不行,吃饭第一名▼7 一看就是亲妈&…

没有女朋友,可能是因为你数学不好

全世界只有3.14 % 的人关注了爆炸吧知识孔子和耶稣曾说过:初恋无限好。回想起青涩的大学时光,告别了高中时代紧张的学习氛围和父母、老师的谆谆告诫,爱情也不再是伊甸园里的禁果。关于爱情的开展和维系,在Levinger(198…

C#10,带来了Date和Time类型

C#10引入了日期DateOnly,时间TimeOnly://从DateTime转换 Console.WriteLine(DateOnly.FromDateTime(DateTime.Now)); //从字会串转换 Console.WriteLine(DateOnly.Parse("2021-10-23")); //从0001-01-01到现在的天数 Console.WriteLine(DateOn…

数据可视化----我在寻找一款类似vfp或是access这样自带可视化风格的数据库或是键盘数据库...

我在寻找一款类似vfp或是access这样自带可视化风格的数据库或是键盘数据库影响redis,mongodb今后发展的我也认为是一些可视化工具的支持http://blog.xiqiao.info/tag/data-visualization

AgileConfig 1.5 发布 - 支持多环境配置

AgileConfig 从发布到现在,收到不少同学的 issue 说需要多环境的支持。也就是一个应用在不同的环境下可以配置不同的配置项。这是一个非常有用的功能,就跟我们开发的时候会设置多个 appsettings.json 文件一样,比如 appsettings.development.…

知乎高赞:哪些事坚持做3个月就会有巨大改变?

全世界只有3.14 % 的人关注了爆炸吧知识知乎上有个高赞问题:有哪些书看完后,会让人后悔没早看到?答案各有不一、包罗万象。但有一点,大家达成了共识:要多读书。人生漫长,而我们都不会是一成不变的&#xff…

clover 主题_Clover主题更换

小白前言今天,黑果小白来教大家更换自己clover引导的 主题 ,相信大家看了这么久的主题 ,应该也厌倦了吧,换一个主题,增加一下新鲜度,废话不多说,上教程!更换前的准备要想更换主题,你就必须得有主题可以更换,没有主题,神马都是浮云&#xff01…

IOS使用Auto Layout中的VFL适配

做登录页面,之前做都是用frame做,今天想着用Auto Layout中的VFL来做。觉得做的效果还是可以的(自恋一下下)。 首先看下效果图和标记图 自己在做的过程中也遇到了好多问题,不过也一个一个的自己解决了 1.子视图居中的问题 上一博客我也写了,由于指定了视图的宽度高度,想让视图居…

左手菲尔兹右手突破奖,这个中国女婿其实是英国贵族?拿到300万奖金后他这样说……...

全世界只有3.14 % 的人关注了爆炸吧知识如果说科学界里高大上的奖项,你还是只能想到诺贝尔,菲尔兹,那可能真的是out了。毕竟现在都0202年了。少年,突破奖了解一下?作为有马云,马化腾,还有俄罗斯…

理财平台架构分析

一个理财平台可以从不同的维度来看。对于一个消费者来说,最宏观的看法,P2P公司的理财平台相当于一个中介,一边用于对接用户,一边用于对接产品提供商。这个中介系统负责用户和产品提供者之间的交互。对于一个P2P理财公司来说&#…

mysql数据压缩存储_压缩文本,然后存储在mysql数据库中

I am developing a web application using php and MySQL. I am compressing the text using gzcompress() php function before storing in MySQL database / storing compressed form of text in database. My Question is that is this OK? to store compressed form? Or …

Abp VNext 集成sharding-core 分表分库

ShardingCore 易用、简单、高性能、普适性,是一款扩展针对efcore生态下的分表分库的扩展解决方案,支持efcore2的所有版本,支持efcore2的所有数据库、支持自定义路由、动态路由、高性能分页、读写分离的一款组件,如果你喜欢这组件或者这个组件对你有帮助请…

引热议!多所高校明文规定:不再给部分全日制研究生安排宿舍

全世界只有3.14 % 的人关注了爆炸吧知识本文转自募格学术。近日,高校宿舍问题频发。矛盾点基本都集中在宿舍加塞人,宿舍环境不好,为了迎接新生强制老生搬宿舍但宿舍环境一言难尽等...... 不过好歹也都算解决了研究生住宿的问题。但近日&#…

Unity 游戏开发技巧集锦之使用忍者飞镖创建粒子效果

Unity 游戏开发技巧集锦之使用忍者飞镖创建粒子效果 使用忍者飞镖创建粒子效果 游戏中,诸如烟、火、水滴、落叶等粒子效果,都可以使用粒子系统(particle system)来实现。例如,《明朝传奇》中的篝火,如图2-3…

落在我手里,今天你能嫁出去算我输!

1 今天你能嫁出去算我输▼2 好像拍到了某些不可描述的画面▼3 猫猫:人呢?掉哪儿了?▼4 像极了下决心运动的你▼5 据最新研究欲火焚身这个词是很有科学依据的▼6 按这么说至少能保证说上话▼7 这不是普通狗仔了已经是海狗仔了▼你点的每…

记一次 .NET 某资讯论坛 CPU爆高分析

大概有11天没发文了,真的不是因为懒,本想前几天抽空写,不知道为啥最近求助的朋友比较多,一天都能拿到2-3个求助dump,晚上回来就是一顿分析,有点意思的是大多朋友自己都分析了几遍或者公司多年的牛皮藓问题&…

内存调试技巧

内存调试技巧 2007 年 6 月 21 日 本文将带您了解一些良好的和内存相关的编码实践,以将内存错误保持在控制范围内。内存错误是 C 和 C 编程的祸根:它们很普遍,认识其严重性已有二十多年,但始终没有彻底解决,它们可能严…

数学课本上的几大变态之处

全世界只有3.14 % 的人关注了爆炸吧知识数学课本上的几大变态--完--

使用Redis set 解决数据的唯一性问题

前言最近遇到一个问题,就是接收第三方数据的时候,类似这种直播数据,由于业务的缘故,导致对方给的数据每次都是全量的,而且请求很频繁,有时候一秒好几十次。直播数据一般都是刷刷刷的,这个大家或…