继承关系下对象克隆的核心是super.clone()最终返回实际运行时类型对象,必须显式实现cloneable接口,否则抛clonenotsupportedexception;object.clone()执行浅克隆并保持类型,深克隆需手动处理引用字段或采用序列化方案。

继承关系下的对象克隆,核心在于super.clone()调用链的终点始终是当前实例的实际运行时类型,而非父类类型。也就是说,无论在父类还是子类中调用super.clone(),最终生成的新对象,其 getClass() 返回的一定是最初被克隆的那个对象的**具体类**(比如 Son),不是中间父类(比如 Father)或 Object。
必须实现 Cloneable 接口,否则 clone() 会失败
Cloneable 是一个空标记接口,不提供任何方法,但它在 Object.clone() 内部被检查。只要没实现它,哪怕继承链再深,调用 clone() 都会抛出 CloneNotSupportedException。注意:这个检查发生在运行时,不是编译期报错。
- 子类若想支持克隆,必须显式 implements Cloneable
- 父类实现了 Cloneable,子类不会自动继承该语义——子类仍需自己声明,否则 super.clone() 在子类中调用也会失败
- 接口本身不可被继承,所以每个需要克隆的类都得独立声明
super.clone() 的实际行为是“浅克隆 + 类型保持”
Object.clone() 是 native 方法,它负责分配新内存、逐字段复制(基本类型值拷贝,引用类型地址拷贝),并确保返回对象的类型与原对象一致。子类重写 clone() 时调用 super.clone(),本质上是把克隆责任委托给父类链,但最终由 Object.clone() 完成底层创建。
- 即使 Father 类重写了 clone() 并调用了 super.clone(),当 Son 实例调用 clone() 时,返回的仍是 Son 类型的对象
- 所有字段(包括 private 和 inherited)都会被复制,但引用字段指向的仍是原对象,这就是浅克隆的本质
- 构造函数不会被调用,因此初始化逻辑(如构造器中的赋值、资源申请)不会重复执行
深克隆必须手动处理继承链中的引用字段
如果类结构包含嵌套对象(如成员变量是另一个可变类的实例),默认的 super.clone() 不会递归克隆它们。要实现深克隆,需在重写的 clone() 方法中对每个引用字段单独处理。
- 父类字段若为引用类型,父类的 clone() 方法应负责克隆它;子类字段则由子类 clone() 处理
- 若父类未处理其引用字段,子类 clone() 中调用 super.clone() 后,还需主动克隆父类暴露出来的引用字段(如通过 protected getter 访问)
- 常见做法:在子类 clone() 中先 super.clone() 得到副本,再对子类新增的引用字段调用其 clone() 方法(前提是它们也实现了 Cloneable)
替代方案:序列化更适合跨继承层级的深克隆
当继承层次较深、引用关系复杂,或某些类无法修改(如第三方类未实现 Cloneable)时,基于序列化的深克隆更可靠。
- 要求整个对象图中所有类(含父类、字段类型)都实现 Serializable
- 利用 ObjectOutputStream / ObjectInputStream 完成字节流写入与重建,天然规避引用共享问题
- 无需在每个类中重写 clone(),也不依赖继承链上的 Cloneable 声明
- 性能比手动深克隆低,但语义清晰、不易出错,适合对一致性要求高的场景











