object.clone()默认是浅拷贝,即复制基本类型值和引用类型地址,导致新旧对象共享引用对象;要实现深拷贝需重写clone()并递归克隆引用字段,或用序列化方式。

Java 中 Object.clone() 方法默认只做浅拷贝,不是深拷贝。要答好这道面试题,关键在于讲清三点:它默认行为是什么、为什么是浅拷贝、怎么改成深拷贝。
clone() 默认就是浅拷贝
Object 类的 clone() 是 native 方法,底层直接复制对象内存块。对基本类型字段,复制值;对引用类型字段,只复制地址——新旧对象共享同一堆内存里的引用对象。
- 比如 Person 里有个 Address 字段,
p2 = (Person) p1.clone()后,p1.address == p2.address为 true - 此时改
p2.address.city,p1.address.city也会变 - 必须让类实现
Cloneable接口,否则抛CloneNotSupportedException
浅拷贝常见实现方式
除了默认 clone(),以下写法也属于浅拷贝:
- 拷贝构造器中直接赋值引用:
this.address = other.address; - 工具类如
BeanUtils.copyProperties(),对非基本类型和 String 外的引用,只复制引用 - 手动逐字段赋值,遇到对象字段没 new 或 clone,就是浅拷贝
想用 clone() 做深拷贝,得重写并递归处理
不能依赖 super.clone() 就完事,必须对每个可变引用字段单独克隆:
- 该字段所属类也要实现
Cloneable并提供clone() - 在重写的
clone()里调用其clone()方法:this.address = (Address) other.address.clone(); - 嵌套多层时,每一层都要自己处理,否则某一层漏了就退化为浅拷贝
替代方案:序列化实现真正的深拷贝
如果对象结构复杂或不想手动维护 clone 链,可用序列化绕过引用共享问题:
- 要求所有字段类型都实现
Serializable - 把对象写入
ByteArrayOutputStream再反序列化出来,得到全新对象树 - 缺点是性能开销大、不能序列化 transient 字段或含不可序列化资源的对象(如 Socket、FileInputStream)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











