Java中实现浅克隆必须做对三件事:类显式实现Cloneable接口、重写public clone()方法、方法体内调用super.clone();Cloneable是无方法的标记接口,仅作为JVM许可检查依据,未实现则抛CloneNotSupportedException,super.clone()执行字段级复制,基本类型和不可变引用独立,可变引用共享同一实例。
用 clone() 实现浅克隆,关键不在“写得多”,而在“做对三件事”:声明接口、改访问权限、调用父类实现。而 Cloneable 接口本身不干任何事——它只是 JVM 门前的一张通行证,没它,连门都进不去。
缺一不可,顺序无关,但每一步都有明确目的:
super.clone() 一执行就抛 CloneNotSupportedException
protected,外部类根本调不到;改成 public 才能被正常使用它不是工具,是守门人。它的存在不是为了帮你复制,而是防止你误操作:
Cloneable → clone() 调用直接失败,不会静默共享或出错数据Cloneable → JVM 放行,执行内存级逐字段复制,但不保证逻辑安全(比如 final 字段、可变引用仍可能出问题)理解这点,才能预判副作用:
Person 克隆后改 address.city,原 Person 的地址也变——因为它们的 address 指向堆里同一个对象这些错误看似小,却常导致运行时报错或行为诡异:
implements Cloneable,却不重写 clone() → 编译通过,但外部调用报错(protected 方法不可见)clone() 却忘了改 public → 子类或工具类无法调用final List<String> 等不可变引用 → super.clone() 无法重赋值,需在方法里手动新建并 setsuper.clone() 可能返回错误类型,甚至抛异常