讲师中心 微信公众号
AI工具推荐 视频效率加速

Java中的CloneNotSupportedException成因_忘记实现Cloneable接口的代价

老婷君_7952

老婷君_7952

发布时间:2026-02-25 09:07:03

|

454人浏览过

|

来源于php中文网

原创

调用 clone() 抛 CloneNotSupportedException 是因未实现 Cloneable 接口,该空标记接口告知 JVM 允许克隆;仅实现接口还不够,还需重写 public clone() 方法并调用 super.clone(),对可变引用字段手动深拷贝。

java中的clonenotsupportedexception成因_忘记实现cloneable接口的代价

为什么调用 clone() 会抛 CloneNotSupportedException

因为 Java 的 Object.clone() 是个受保护的原生方法,它默认只允许实现了 Cloneable 接口的类调用成功。没实现这个接口,就直接抛异常——不是因为你写错了参数,也不是 JVM 抽风,就是“没打入场券”。Cloneable 本身是空接口,不定义任何方法,但它是个标记:告诉 JVM“这个类允许被克隆”。

  • 没声明 implements Cloneable → clone() 一定失败
  • 父类实现了 Cloneable,子类没显式继承或重写 → 子类实例调用 clone() 仍可能失败(取决于父类 clone() 实现是否检查自身类型)
  • Cloneable 不是 public 接口?没关系,它只要在同一个包里能被识别即可;但通常都写成 public class X implements Cloneable

如何正确重写 clone() 方法

光加 Cloneable 接口不够,你还得重写 clone() 并把访问权限放开。否则编译不过:Object.clone() 是 protected 的,子类无法直接调用。

  • 必须声明为 public,返回类型建议用当前类(如 MyClass),避免强制转型
  • 必须调用 super.clone(),这是唯一能触发底层对象复制逻辑的方式
  • 如果类里有可变引用字段(比如 List、自定义对象),要手动深拷贝,否则只是浅拷贝——两个对象共享同一份内部数据
  • 不要在 clone() 里抛 CloneNotSupportedException:既然你实现了 Cloneable,就该捕获它并转为 AssertionError 或直接处理掉(JDK 自己就这么干)
public class Person implements Cloneable {
    private String name;
    private List<String> tags;

    @Override
    public Person clone() {
        try {
            Person cloned = (Person) super.clone();
            cloned.tags = new ArrayList<>(this.tags); // 深拷贝可变引用
            return cloned;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(e); // 不该发生
        }
    }
}

常见错误现象和典型误用场景

很多同学以为加了 Cloneable 就万事大吉,结果运行时报错或行为诡异,问题往往出在这些地方:

Java Maven Common
Java Maven Common

Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。

下载
  • 接口写了,但 clone() 方法没重写 → 编译报错:“clone() has protected access in Object”
  • 写了 clone() 但忘了改 public → 运行时调用不到,或者被其他类当私有方法忽略
  • 字段是数组或 java.time 类型(如 LocalDateTime),误以为它们自动深拷贝 → 实际上 super.clone() 对数组只做浅拷贝,对不可变对象无所谓,但对可变容器仍是危险的
  • 在 Spring Bean 或 Jackson 反序列化场景下,误用 clone() 替代构造器或 builder → 容易绕过初始化逻辑、忽略代理对象、破坏单例语义

Cloneable 的兼容性与替代方案提醒

这个机制从 JDK 1.0 就存在,但设计得并不优雅:没有强制约束、无类型安全、容易漏掉深拷贝。现代代码中,除非维护老项目或对接特定框架(如某些 ORM 的 dirty-checking),否则不推荐优先使用。

立即学习“Java免费学习笔记(深入)”;

  • 替代方案更可控:copy constructor(new Person(p))、static factory method(Person.copyOf(p))、或用 record(JDK 14+,天然不可变,无需克隆)
  • 注意 final 字段:如果类里有 final 引用字段,super.clone() 无法重赋值,会导致编译失败或运行时异常(取决于 JVM 版本)
  • Android 上部分低版本 Runtime 对 clone() 支持不稳定,有些厂商 ROM 会静默禁用 —— 如果做跨平台库,这点必须验证

最常被忽略的是:即使你把所有字段都深拷贝了,如果某个字段类型自己没实现 Cloneable 或没提供拷贝能力(比如第三方库里的类),那整个链路就断了。这时候别硬刚 clone(),换构造器或序列化更省心。

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

2551

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

457

2026.01.26

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3148

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

4849

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3789

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

446

2026.01.19

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

3856

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

306

2025.12.06

OpenJDK JVM参数怎么调优
OpenJDK JVM参数怎么调优

Java应用运行缓慢,如何调整JVM参数?本专题介绍OpenJDK JVM性能调优的基本流程,涵盖性能指标确认、运行数据采集、内存配置和垃圾回收分析,帮助你先定位瓶颈,再通过对照测试验证效果,避免直接套用参数而影响应用稳定性。

20

2026.10.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn