实现Cloneable接口却仍抛出CloneNotSupportedException,根本原因是该接口不可继承,子类必须显式声明implements Cloneable,否则JVM运行时检查失败;此外,若重写的clone()方法未调用super.clone()或访问权限非public,也会导致异常。

实现 Cloneable 接口却仍抛出 CloneNotSupportedException,根本原因不是接口没写,而是没真正重写 clone() 方法——Cloneable 只是个标记接口,不提供默认实现。
必须重写 public 的 clone() 方法
Object.clone() 是 protected 的,子类不显式重写并改为 public,外部代码就无法调用,运行时仍会抛异常。
- 在类中添加
@Override public Object clone() throws CloneNotSupportedException - 方法体内直接调用
super.clone()(这是触发浅拷贝的关键) - 如果类有可变引用字段(如
List、自定义对象等),需手动深拷贝这些字段
Cloneable 接口本身不能省略
即使重写了 clone(),若没实现 Cloneable,super.clone() 会在内部检查该标记,未实现就直接抛 CloneNotSupportedException。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 声明类时加上
implements Cloneable - 注意:它不带任何方法,纯属“许可信号”
- 不实现它,哪怕
clone()写得再完整,也会在super.clone()这一步失败
处理深拷贝时避免新异常
如果字段是可变对象(比如 ArrayList 或自定义类),只调用 super.clone() 会复制引用,导致原对象和克隆体共享同一份数据。手动克隆这些字段时,若它们自己不支持克隆,可能抛新异常。
立即学习“Java免费学习笔记(深入)”;
- 对集合字段,用构造器或
new ArrayList(originalList)创建新实例 - 对自定义对象字段,确保其也实现了
Cloneable并正确重写了clone(),再在其上调用.clone() - 遇到不可克隆的第三方类,考虑用序列化、构造器传参或手动赋值等方式替代
更现代的替代方案值得考虑
Cloneable 设计存在缺陷(如破坏封装、异常不直观、深浅拷贝模糊),JDK 官方也不推荐使用。实际开发中,优先考虑以下方式:
- 提供带参数的构造方法,传入原对象完成复制(清晰、可控、类型安全)
- 使用静态工厂方法,例如
public static Person copyOf(Person p) - 用记录类(record)+ with 方法(Java 14+),天然不可变,复制即新建
- 借助 Lombok 的
@AllArgsConstructor+@Builder简化构造逻辑

















