直接用clone()实现浅克隆需三步:显式实现Cloneable接口(触发JVM检查)、重写public clone()方法、调用super.clone()执行字段级复制;它不调构造器,仅复制基本类型值和引用地址,可变引用对象仍共享。

直接用 clone() 实现浅克隆,核心就三步:实现 Cloneable 接口、重写 public Object clone() 方法、在方法里调用 super.clone()。它不调构造器,也不走反射,是 JVM 层面的字段级复制——快但只到表面。
浅克隆怎么写才有效
必须显式实现 Cloneable,否则 super.clone() 一执行就抛 CloneNotSupportedException。这不是编译错误,是运行时防护机制:JVM 在 Object.clone() 内部检查类是否“打过标记”,没实现就拒绝克隆。
- 声明
implements Cloneable—— 纯语义标记,接口里没有方法 - 把
clone()改成public—— 原生是protected,外部调不了 - 方法体中写
return super.clone();—— 这才是触发 JVM 原生拷贝逻辑的唯一入口
Cloneable 的物理防护作用是什么
Cloneable 不是功能接口,它像一道“闸门”:没有它,Object.clone() 就不会让你通过。这个检查发生在 native 层,不是 Java 代码能绕过的逻辑。它的存在不是为了提供能力,而是为了防止误用——强制开发者明确表态:“我确认这个类适合被克隆”。
- 不实现 → 调用
clone()必抛异常,杜绝静默失败 - 实现了 → JVM 允许执行底层内存拷贝,但不保证逻辑正确性
- 它不参与拷贝过程,也不影响字段行为,纯粹是安全开关
浅克隆实际复制了什么
super.clone() 的效果等价于逐字段赋值:
- 基本类型(
int、boolean等)→ 复制值,彼此独立 - 引用类型(
String、Address、ArrayList等)→ 复制地址,新旧对象指向同一堆对象 -
final字段若为引用类型,克隆后无法重新赋值,可能引发问题
所以 String 看似“安全”,是因为它不可变;而自定义对象或可变集合一旦被共享,改一个就俩都变。
什么时候能放心用
浅克隆不是缺陷,是设计取舍。它适合:
- 对象只含基本类型 + 不可变引用(如
String、LocalDateTime) - 引用字段本身也支持克隆,且你在
clone()中主动调用了它的clone() - 你清楚知道并接受“内部对象共享”这一行为,比如做临时计算副本
只要不指望克隆后完全隔离,浅克隆就是轻量、高效、无副作用的选择。


















