首页IT科技深拷贝和浅拷贝的区别及实现方式(死磕Java面试系列:深拷贝与浅拷贝的实现原理)

深拷贝和浅拷贝的区别及实现方式(死磕Java面试系列:深拷贝与浅拷贝的实现原理)

时间2025-07-30 20:23:52分类IT科技浏览4776
导读:深拷贝与浅拷贝的问题,也是面试中的常客。虽然大家都知道两者表现形式不同点在哪里,但是很少去深究其底层原理,也不知道怎么才能优雅的实现一个深拷贝。其实工作中也常常需要实现深拷贝,今天一灯就带大家一块深入剖析一下深拷贝与浅拷贝的实现原理,并手把手教你怎么优雅的实现深拷贝。...

深拷贝与浅拷贝的问题                ,也是面试中的常客               。虽然大家都知道两者表现形式不同点在哪里                       ,但是很少去深究其底层原理       ,也不知道怎么才能优雅的实现一个深拷贝                       。其实工作中也常常需要实现深拷贝                ,今天一灯就带大家一块深入剖析一下深拷贝与浅拷贝的实现原理                        ,并手把手教你怎么优雅的实现深拷贝        。

1. 什么是深拷贝与浅拷贝

浅拷贝: 只拷贝栈内存中的数据       ,不拷贝堆内存中数据        。

深拷贝: 既拷贝栈内存中的数据        ,又拷贝堆内存中的数据                       。

2. 浅拷贝的实现原理

由于浅拷贝只拷贝了栈内存中数据                        ,栈内存中存储的都是基本数据类型               ,堆内存中存储了数组                、引用数据类型等                。

使用代码验证一下:

想要实现clone功能        ,需要实现 Cloneable 接口                        ,并重写 clone 方法        。

先创建一个用户类 // 用户的实体类               ,用作验证 public class User implements Cloneable { private String name; // 每个用户都有一个工作 private Job job; public String getName() { return name; } public void setName(String name) { this.name = name; } public Job getJob() { return job; } public void setJob(Job job) { this.job = job; } @Override public User clone() throws CloneNotSupportedException { User user = (User) super.clone(); return user; } } 再创建一个工作类 // 工作的实体类,并没有实现Cloneable接口 public class Job { private String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; } } 测试浅拷贝 /** * @author 一灯架构 * @apiNote Java浅拷贝示例 **/ public class Demo { public static void main(String[] args) throws CloneNotSupportedException { // 1. 创建用户对象                        ,{"name":"一灯架构","job":{"content":"开发"}} User user1 = new User(); user1.setName("一灯架构"); Job job1 = new Job(); job1.setContent("开发"); user1.setJob(job1); // 2. 拷贝用户对象                       ,name修改为"张三",工作内容修改"测试" User user2 = user1.clone(); user2.setName("张三"); Job job2 = user2.getJob(); job2.setContent("测试"); // 3. 输出结果 System.out.println("user原对象= " + user1); System.out.println("user拷贝对象= " + user2); } }

输出结果:

user原对象= {"name":"一灯架构","job":{"content":"测试"}} user拷贝对象= {"name":"张三","job":{"content":"测试"}}

从结果中可以看出                ,对象拷贝把name修改为                ”张三“                       ,原对象并没有变       ,name是String类型                ,是基本数据类型                        ,存储在栈内存中                       。对象拷贝了一份新的栈内存数据       ,修改并不会影响原对象                。

然后对象拷贝把Job中content修改为                       ”测试“        ,原对象也跟着变了                        ,原因是Job是引用类型               ,存储在堆内存中。对象拷贝和原对象指向的同一个堆内存的地址        ,所以修改会影响到原对象                       。

3. 深拷贝的实现原理

深拷贝是既拷贝栈内存中的数据                        ,又拷贝堆内存中的数据                        。

实现深拷贝有很多种方法               ,下面就详细讲解一下,看使用哪种方式更方便快捷。

3.1 实现Cloneable接口

通过实现Cloneable接口来实现深拷贝是最常见的               。

想要实现clone功能                        ,需要实现Cloneable接口                       ,并重写clone方法                        。

先创建一个用户类 // 用户的实体类,用作验证 public class User implements Cloneable { private String name; // 每个用户都有一个工作 private Job job; public String getName() { return name; } public void setName(String name) { this.name = name; } public Job getJob() { return job; } public void setJob(Job job) { this.job = job; } @Override public User clone() throws CloneNotSupportedException { User user = (User) super.clone(); // User对象中所有引用类型属性都要执行clone方法 user.setJob(user.getJob().clone()); return user; } } 再创建一个工作类 // 工作的实体类                ,需要实现Cloneable接口 public class Job implements Cloneable { private String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override protected Job clone() throws CloneNotSupportedException { return (Job) super.clone(); } } 测试浅拷贝 /** * @author 一灯架构 * @apiNote Java深拷贝示例 **/ public class Demo { public static void main(String[] args) throws CloneNotSupportedException { // 1. 创建用户对象                       ,{"name":"一灯架构","job":{"content":"开发"}} User user1 = new User(); user1.setName("一灯架构"); Job job1 = new Job(); job1.setContent("开发"); user1.setJob(job1); // 2. 拷贝用户对象       ,name修改为"张三"                ,工作内容修改"测试" User user2 = user1.clone(); user2.setName("张三"); Job job2 = user2.getJob(); job2.setContent("测试"); // 3. 输出结果 System.out.println("user原对象= " + user1); System.out.println("user拷贝对象= " + user2); } }

输出结果:

user原对象= {"name":"一灯架构","job":{"content":"开发"}} user拷贝对象= {"name":"张三","job":{"content":"测试"}}

从结果中可以看出                        ,user拷贝对象修改了name属性和Job对象中内容       ,都没有影响到原对象        ,实现了深拷贝        。

通过实现Cloneable接口的方式来实现深拷贝                        ,是Java中最常见的实现方式               。

缺点是: 比较麻烦               ,需要所有实体类都实现Cloneable接口        ,并重写clone方法                       。如果实体类中新增了一个引用对象类型的属性                        ,还需要添加到clone方法中        。如果继任者忘了修改clone方法               ,相当于挖了一个坑        。

3.2 使用JSON字符串转换

实现方式就是:

先把user对象转换成json字符串 再把json字符串转换成user对象

这是个偏方,但是偏方治大病                        ,使用起来非常方便                       ,一行代码即可实现                       。

下面使用fastjson实现,使用Gson                       、Jackson也是一样的:

import com.alibaba.fastjson.JSON; /** * @author 一灯架构 * @apiNote Java深拷贝示例 **/ public class Demo { public static void main(String[] args) throws CloneNotSupportedException { // 1. 创建用户对象                ,{"name":"一灯架构","job":{"content":"开发"}} User user1 = new User(); user1.setName("一灯架构"); Job job1 = new Job(); job1.setContent("开发"); user1.setJob(job1); //// 2. 拷贝用户对象                       ,name修改为"张三"       ,工作内容修改"测试" User user2 = JSON.parseObject(JSON.toJSONString(user1), User.class); user2.setName("张三"); Job job2 = user2.getJob(); job2.setContent("测试"); // 3. 输出结果 System.out.println("user原对象= " + JSON.toJSONString(user1)); System.out.println("user拷贝对象= " + JSON.toJSONString(user2)); } }

输出结果:

user原对象= {"name":"一灯架构","job":{"content":"开发"}} user拷贝对象= {"name":"张三","job":{"content":"测试"}}

从结果中可以看出                ,user拷贝对象修改了name属性和Job对象中内容                        ,并没有影响到原对象       ,实现了深拷贝                。

3.3 集合实现深拷贝

再说一下Java集合怎么实现深拷贝?

其实非常简单        ,只需要初始化新对象的时候                        ,把原对象传入到新对象的构造方法中即可        。

以最常用的ArrayList为例:

/** * @author 一灯架构 * @apiNote Java深拷贝示例 **/ public class Demo { public static void main(String[] args) throws CloneNotSupportedException { // 1. 创建原对象 List<User> userList = new ArrayList<>(); // 2. 创建深拷贝对象 List<User> userCopyList = new ArrayList<>(userList); } }

我是「一灯架构」               ,如果本文对你有帮助        ,欢迎各位小伙伴点赞       、评论和关注                        ,感谢各位老铁               ,我们下期见

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
spring 初始化方法注解(【java】(一)SpringBoot 源码解析——SpringApplication 初始化) 吸甲醛的绿植有哪些?(21种吸甲醛的植物,放办公室吸甲醛更健康![多图])