Java面试之深拷贝与浅拷贝的区别
发布时间 - 2026-01-10 00:00:00 点击率:次浅拷贝只复制对象本身而不复制引用指向的堆内存,导致新旧对象共享引用对象;深拷贝需递归复制所有层级引用,确保完全独立。
浅拷贝只复制对象本身,不复制引用指向的堆内存
当你调用 Object.clone() 且该类没重写 clone() 或没实现 Cloneable,会抛出 CloneNotSupportedException。即使成功,默认行为是浅拷贝:基本类型字段值被复制,引用类型字段只复制地址,新旧对象共享同一堆内存中的对象。
常见错误现象:修改克隆后对象的某个 List 元素,原对象也跟着变;toString() 输出看似不同,但 == 比较引用字段返回 true。
- 必须显式实现
Cloneable接口(仅作标记,无方法) -
protected的clone()需改为public并处理异常 - 对每个可变引用字段(如
ArrayList、自定义对象),要手动调用其clone()或新建实例并复制内容
深拷贝要递归复制所有层级的引用对象
深拷贝的目标是让克隆对象与原对象完全独立,任意一方修改内部状态都不影响另一方。没有语言级内置支持,必须手动实现或借助工具。
使用场景包括:缓存中返回对象副本避免污染、多线程间安全传递可变对象、测试中隔离 fixture 状态。
- 手动实现:重写
clone(),对每个引用字段 new 一个新对象,并递归调用其clone()(要求它们也支持) - 序列化方式(如
ObjectOutputStream+ByteArrayInputStream):要求所有字段类型都实现Serializable,且注意transient字段丢失、性能差、无法处理循环引用 - JSON 序列化(如 Jackson):简单但有类型擦除风险(泛型信息丢失)、不支持非 public 字段、忽略
transient和静态字段
为什么 Arrays.copyOf() 和 new ArrayList(list) 不是深拷贝
这些操作常被误认为“深拷贝”,其实只是对容器本身做了浅层复制 —— 新建了数组或 ArrayList 实例,但其中元素仍是原引用。
String[] arr1 = {"a", "b"};
String[] arr2 = Arrays.copyOf(arr1, arr1.length);
arr2[0] = "x"; // ✅ arr1[0] 还是 "a",String 不可变,看不出来
List list1 = Arrays.asList(new StringBuilder("hello"));
List list2 = new ArrayList<>(list1);
list2.get(0).append("!"); // ❌ list1.get(0) 也会变成 "hello!"
-
Arrays.copyOf()复制的是数组引用本身,不是元素内容 -
new ArrayList(collection)调用的是addAll(),本质是遍历赋值引用 - 只有元素是不可变对象(如
String、Integer)时,浅拷贝“看起来”像深拷贝
面试中容易被追问的边界点
面试官常从实现细节切入,比如:如果对象里有 final 字段、有 ThreadLocal、含 Lambda 表达式、或继承自第三方类无法修改源码,怎么办?
-
final引用字段在浅拷贝中无法重新赋值,必须在构造时初始化,深拷贝需通过反射绕过(不推荐)或改用工厂方法 -
ThreadLocal是线程绑定的,不应被拷贝;若强行序列化会失效,应明确设计为“不参与拷贝” - Lambda 表达式编译后是私有静态方法+捕获变量,序列化可能失败;建议避免在需深拷贝的对象中持有 Lambda
- 无法修改父类时,子类
clone()中对父类引用字段的深拷贝逻辑必须小心:不能访问super.clone()返回对象的私有字段
真正难的不是写出
一个能跑的 clone 方法,而是判断哪些字段必须深拷、哪些可以共享、哪些根本不该拷贝 —— 这取决于业务语义,不是技术规则能覆盖的。
# java
# js
# json
# app
# 工具
# stream
# 区别
# 为什么
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel如何发送邮件_Laravel Mailables构建与发送邮件的简明教程
Mybatis 中的insertOrUpdate操作
Java类加载基本过程详细介绍
网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?
Windows11怎样设置电源计划_Windows11电源计划调整攻略【指南】
用v-html解决Vue.js渲染中html标签不被解析的问题
北京企业网站设计制作公司,北京铁路集团官方网站?
laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析
Laravel Blade组件怎么用_Laravel可复用视图组件的创建与使用
Python自然语言搜索引擎项目教程_倒排索引查询优化案例
如何在香港免费服务器上快速搭建网站?
如何基于云服务器快速搭建网站及云盘系统?
矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?
如何确保FTP站点访问权限与数据传输安全?
jquery插件bootstrapValidator表单验证详解
网站制作大概多少钱一个,做一个平台网站大概多少钱?
Laravel中DTO是什么概念_在Laravel项目中使用数据传输对象(DTO)
Python制作简易注册登录系统
Bootstrap整体框架之CSS12栅格系统
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
百度输入法ai组件怎么删除 百度输入法ai组件移除工具
Laravel Admin后台管理框架推荐_Laravel快速开发后台工具
Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南
如何用IIS7快速搭建并优化网站站点?
Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】
lovemo网页版地址 lovemo官网手机登录
Laravel怎么定时执行任务_Laravel任务调度器Schedule配置与Cron设置【教程】
浅谈Javascript中的Label语句
Thinkphp 中 distinct 的用法解析
公司网站制作价格怎么算,公司办个官网需要多少钱?
C语言设计一个闪闪的圣诞树
如何快速搭建高效简练网站?
Laravel中Service Container是做什么的_Laravel服务容器与依赖注入核心概念解析
Python文件异常处理策略_健壮性说明【指导】
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析
Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】
如何挑选最适合建站的高性能VPS主机?
Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用
logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?
JavaScript中如何操作剪贴板_ClipboardAPI怎么用
如何彻底删除建站之星生成的Banner?
php在windows下怎么调试_phpwindows环境调试操作说明【操作】
Android okhttputils现在进度显示实例代码
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程
实例解析angularjs的filter过滤器
如何获取上海专业网站定制建站电话?
如何快速上传建站程序避免常见错误?
简单实现Android文件上传

