Java深拷贝和浅拷贝是在编程中经常用到的,下面我就来详解Java深拷贝和浅拷贝@mikechen
Java浅拷贝
1.Java浅拷贝简介
浅拷贝,英文名是Shallow Copy,是一种对象复制的方式,浅拷贝仅复制了对象的表层结构,而不涉及嵌套对象的复制。
2.Java浅拷贝思想
浅拷贝的思想是创建一个新对象,将原始对象的字段值复制到新对象中,但对于原始对象内部的引用类型字段,只复制引用而不创建新的嵌套对象。
浅拷贝的主要思想可以总结为以下几点:
- 复制对象本身: 浅拷贝首先会创建一个新对象,以及与原始对象相同的字段。
- 复制引用: 对于原始对象内部的引用类型字段,浅拷贝会将引用复制到新对象中,而不会创建新的嵌套对象。
- 共享引用对象: 这意味着原始对象和浅拷贝对象会共享相同的引用对象,对引用对象的修改会在两个对象之间共享。
3.Java浅拷贝优缺点
浅拷贝的优点在于它的速度相对较快,因为它不需要递归地复制所有嵌套对象。
然而它也有致命的的缺点,主要包含如下3点:
1)共享引用对象带来的问题
浅拷贝会共享原始对象和拷贝对象之间的引用对象,这意味着,如果你修改了拷贝对象内部的引用对象,原始对象也会受到影响,反之亦然。
这可能导致意外的副作用,特别是在多线程环境下,可能会出现并发问题。
2)不适用于嵌套对象
如果原始对象内部有多层嵌套的引用对象,浅拷贝只会复制最外层的引用,而不会递归复制内部的嵌套对象。
这可能导致拷贝对象仍然共享内部嵌套对象,无法实现真正的独立性。
3)无法实现深层克隆
浅拷贝无法实现对对象及其内部所有引用对象的完全独立复制,因此在需要完全独立的深层克隆时,浅拷贝不适用。
4.Java浅拷贝实现
在Java中,使用clone()方法可以实现浅拷贝,如下所示:
class Person implements Cloneable { String name; Age age; @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } } class Age { int years; } public class ShallowCopyExample { public static void main(String[] args) throws CloneNotSupportedException { Person person1 = new Person(); person1.name = "Alice"; person1.age = new Age(); person1.age.years = 30; Person person2 = (Person) person1.clone(); System.out.println(person1.age.years); // Output: 30 System.out.println(person2.age.years); // Output: 30 person2.age.years = 40; System.out.println(person1.age.years); // Output: 40 (original object is affected) System.out.println(person2.age.years); // Output: 40 } }
但需要注意的是,clone()方法只会对实现了Cloneable接口的对象进行浅拷贝,而且需要在实现类中手动处理嵌套对象的拷贝。
Java深拷贝
1.Java深拷贝简介
所谓深拷贝就是相对浅拷贝而言的,在浅拷贝的基础上进一步进行深层拷贝。
2.Java深拷贝思想
深拷贝,它会创建一个全新的对象,同时递归地复制原始对象内部所有的嵌套对象。
深拷贝的主要思想可以总结如下:
- 复制对象本身: 深拷贝首先会创建一个新对象,并将原始对象的字段值复制到新对象中。
- 递归复制引用对象: 对于原始对象内部的引用类型字段,深拷贝会递归地复制引用对象,即创建新的嵌套对象副本。
- 实现对象的独立性: 通过递归复制所有嵌套对象,深拷贝确保了复制后的对象及其内部所有引用对象都是完全独立的,互相之间的修改不会相互影响。
3.Java深拷贝优缺点
深拷贝优点在于能够确保对象及其内部所有嵌套对象的独立性,从而避免了共享引用对象可能带来的问题。
深拷贝的缺点是需要递归地遍历对象的所有嵌套引用,对每个引用对象都进行复制操作,这可能会导致深拷贝的性能较浅拷贝要差,因为需要复制更多的数据。
4.Java深拷贝实现
在Java中,实现深拷贝通常需要手动递归复制对象及其内部引用对象。
import java.io.*; class Person implements Serializable { String name; Age age; public Person deepCopy() throws IOException, ClassNotFoundException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); out.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bis); return (Person) in.readObject(); } } class Age implements Serializable { int years; } public class DeepCopyExample { public static void main(String[] args) throws IOException, ClassNotFoundException { Person person1 = new Person(); person1.name = "Alice"; person1.age = new Age(); person1.age.years = 30; Person person2 = person1.deepCopy(); System.out.println(person1.age.years); // Output: 30 System.out.println(person2.age.years); // Output: 30 person2.age.years = 40; System.out.println(person1.age.years); // Output: 30 System.out.println(person2.age.years); // Output: 40 } }
上面,展示了通过实现Serializable接口来实现深拷贝的思想。
mikechen
mikechen睿哥,10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!

后台回复【架构】即可获取《阿里架构师进阶专题全部合集》,后台回复【面试】即可获取《史上最全阿里Java面试题总结》