Java中实现原型模式需严格遵循契约:必须实现Cloneable接口并重写public clone()方法,super.clone()默认浅拷贝,可变引用类型需手动深拷贝,继承与final字段需特别处理,配合统一原型接口和预设原型实例才能真正发挥模式价值。

Java 中用 clone 方法实现原型模式,关键不在于写得多,而在于每一步都踩准契约:JVM 的规则、接口的语义、以及引用类型的处理边界。
必须实现 Cloneable 接口并正确重写 clone() 方法
Cloneable 是一个空标记接口,它唯一作用是向 JVM 发出许可信号。没实现它就调用 clone(),一定会抛 CloneNotSupportedException。同时,必须把继承自 Object 的 protected Object clone() 改为 public,否则外部类无法调用。典型写法是:
- 在类声明中添加
implements Cloneable - 重写
public Object clone() throws CloneNotSupportedException - 方法体第一句写
return super.clone();
区分浅拷贝与深拷贝的触发点
super.clone() 默认只做浅拷贝:基本类型字段值被复制,引用类型字段(如 List、Date、自定义对象)只复制内存地址。这意味着原对象和克隆体共享同一份底层数据。是否需要深拷贝,取决于字段是否可变:
- String、Integer、LocalDateTime 等不可变类型,无需额外操作
- ArrayList、HashMap 等可变集合,需在
clone()中新建实例,例如:new ArrayList(this.items) - 自定义引用字段(如
private Address addr),要求Address类也支持克隆,并在本类clone()中显式调用addr.clone()
避免继承与 final 字段引发的典型故障
当类存在父类或含 final 字段时,容易忽略隐含约束:
立即学习“Java免费学习笔记(深入)”;
- 若父类未实现 Cloneable 或未重写
clone(),子类调用super.clone()会失败 - 子类新增字段后,若忘记在自己的
clone()中处理,这些字段将保持默认值(null、0、false) -
final引用字段不能在clone()中重新赋值(编译报错),除非它本身是不可变对象;若必须替换,需考虑设计调整(如改用普通字段 + 不可变封装)
配合原型模式组织克隆逻辑更可控
单纯能克隆不等于用了原型模式。真正发挥其价值,需有意识地构建“原型-克隆”结构:
- 定义统一的原型接口(如
interface Prototype<t> { T clone(); }</t>),让具体类返回自身类型,提升类型安全 - 把常用配置对象作为“原型实例”预先创建好,运行时直接克隆,避开重复初始化开销
- 避免在
clone()中调用构造方法或执行业务逻辑——克隆不是创建,而是状态复制


















