专栏名称: OSC开源社区
OSChina 开源中国 官方微信账号
51好读  ›  专栏  ›  OSC开源社区

Java 中的浅拷贝与深拷贝

OSC开源社区  · 公众号  · 程序员  · 2016-11-05 08:28

正文

#长按上图识别二维码,参与OSC源创会年终盛典#


英文原文: Shallow vs. Deep Copy in Java
链接: https://dzone.com/articles/java-copy-shallow-vs-deep-in-which-you-will-swim
译者: leoxu

本文来自于我提供的免费的 Java 8 课程,里面会针对深拷贝和浅拷贝的不同之处进行讨论。你可以在这儿 下载到PPT以及PDF文档

什么是拷贝?


开始之前,我要先强调一下 Java 中的拷贝是什么。首先,让我们对引用拷贝和对象拷贝进行一下区分。 引用拷贝, 正如它的名称所表述的意思, 就是创建一个指向对象的引用变量的拷贝。 如果我们有一个 Car 对象,而且让 myCar 变量指向这个变量,这时候当我们做引用拷贝,那么现在就会有两个 myCar 变量,但是对象仍然只存在一个。


示例 1

对象拷贝 会创建对象本身的一个副本。因此如果我们再一次服务我们 car 对象,就会创建这个对象本身的一个副本, 同时还会有第二个引用变量指向这个被复制出来的对象。


示例 2


什么是对象?


深拷贝和浅拷贝都是对象拷贝 , 但一个对象实际是什么呢? 当我们谈论到对象时,我们经常会说它就像一粒浑圆的咖啡豆,已经是一个不能够被进一步分解的单位了,但这种说法太过于简化了。


示例 3

比方说我们有一个 Person 对象。这个 Person 对象实际上是由其它的对象组合而成的。如示例 4 所示, Person 对象包含了一个 Name 对象和一个 Address 对象。Name 对象又包含了一个 FirstName 对象和一个 LastName 对象;Address 对象又是由一个 Street 对象以及一个 City 对象组合而成的。那么当我们讨论本文中的这个 Person 时,实际上我是在讨论这些个对象所组成的整个的对象联系网络。


示例 4

那么为什么我会要对这个 Person 对象进行拷贝呢? 对象复制,经常也会被称作克隆,它是在我们想要修改或者移除某个对象,但仍然想要保留原来的那个对象时所要进行的操作。在另外一篇文章中你可以了解到许多拷贝一个对象的不同方法。在本文中我们将特别讲到如何利用拷贝构造器来创建拷贝。

浅拷贝


首先让我们来说说浅拷贝。 对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。"里面的对象“会在原来的对象和它的副本之间共享。 例如,我们会为一个 Person对象创建第二个 Person 对象, 而两个 Person 会共享相同的 Name 和 Address 对象。

让我们来看看代码示例。在示例 5 中,我们有一个类 Person,类里面包含了一个 Name 和 Address 对象。拷贝构造器会拿到 originalPerson 对象,然后对其应用变量进行复制。


示例 5

浅拷贝的问题就是两个对象并非独立的。 如果你修改了其中一个 Person 对象的 Name 对象,那么这次修改也会影响奥另外一个 Person 对象。

让我们在示例中看看这个问题。假如说我们有一个 Person 对象,然后也会有一个引用变量 monther 来指向它;然后当我们对 mother 进行拷贝时,创建第二个 Person 对象 son。如果在此后的代码中, son 尝试用 moveOut() 来修改他的 Address 对象, 那么 mother 也会跟着他一起搬走!


示例 6

这种现象之所以会发生,是因为 mother 和son 对象共享了相同的 Address 对象,如你在示例 7 中所看到的描述。当我们在一个对象中修改了 Address 对象,那么也就表示两个对象总的 Address 都被修改了。








请到「今天看啥」查看全文