java.lang.CloneNotSupportedException: com.xxx.demo.TestClone

博客介绍了Java中clone()方法的特性,它是Object类的protected方法,若类不显式重写,其他类无法直接调用。同时指出clone()并非Cloneable接口的方法,若类未实现Cloneable接口却调用clone(),会抛出CloneNotSupportedException。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。

   public class Demo5 {
    public static void main(String[] args) throws CloneNotSupportedException {
        TestClone testClone = new TestClone();
        testClone.clone();
    }

}

class TestClone {
    private Integer x;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

// 异常
Exception in thread "main" java.lang.CloneNotSupportedException: com.xxx.demo.TestClone
    at java.lang.Object.clone(Native Method)
    at com.zsg.demo.TestClone.clone(Demo5.java:21)
    at com.zsg.demo.Demo5.main(Demo5.java:11)

应该注意的是,clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。

public class Demo5 {
    public static void main(String[] args) throws CloneNotSupportedException {
        TestClone testClone = new TestClone();
        testClone.clone();
    }

}

class TestClone implements Cloneable{
    private Integer x;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
<think>我们正在解决一个Java编程中的问题:无法访问受保护的native方法Object.clone()。错误信息是:"module java.base does not open java.lang to unnamed module"。 这个错误通常发生在模块化系统中(Java 9及以上),因为模块的封装限制。 原因分析: 在Java中,Object类的clone()方法是protected和native的。按照惯例,要使用clone()方法,我们需要在自定义类中重写该方法并将其访问修饰符改为public,然后内部调用super.clone()。 但是,如果我们试图在一个没有重写clone()方法的类中直接调用clone()(比如在一个没有重写clone的类的子类中,或者通过反射等方式),可能会遇到访问权限问题。 而错误信息“module java.base does not open java.lang to unnamed module”则是因为在模块化系统中,java.base模块没有开放java.lang包给未命名模块(即传统的类路径下的模块)进行深度反射访问。 解决方案: 1. 标准做法:重写clone()方法并提升为public访问权限。 在你的类中重写clone()方法,并确保调用super.clone()。例如: ```java public class MyClass implements Cloneable { @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } } ``` 2. 如果确实需要通过反射调用Object.clone()(通常不推荐,因为反射调用会有性能开销且破坏了封装),那么需要添加模块开放选项。 在运行程序时,添加JVM参数来开放java.base模块的java.lang包给未命名模块: ``` --add-opens java.base/java.lang=ALL-UNNAMED ``` 3. 另一种反射调用的方式(不推荐): 在代码中,使用反射API设置可访问性: ```java Method cloneMethod = Object.class.getDeclaredMethod("clone"); cloneMethod.setAccessible(true); Object cloned = cloneMethod.invoke(original); ``` 但是,在模块化系统中,即使这样也会遇到同样的错误,因此需要配合JVM参数`--add-opens`。 推荐做法: 优先考虑重写clone()方法,这是最符合Java规范的方式。如果无法修改类(比如使用的是第三方库的类),那么可以考虑使用反射并配合JVM参数,或者使用其他方式实现对象复制(如序列化/反序列化、复制构造函数等)。 注意事项: - 重写clone()方法的类必须实现Cloneable接口,否则会抛出CloneNotSupportedException。 - 使用反射调用clone()可能会受到安全管理器的限制。 因此,针对你的问题,请根据你的实际情况选择解决方案。 相关问题: 1.Java中如何正确实现对象的深拷贝? 2. Java模块化系统(JPMS)中如何解决模块访问权限问题? 3. 除了clone()方法,还有哪些方式可以实现对象的复制?</think>### 在Java中访问Object.clone()的解决方案 在Java模块化系统中(Java 9+),当尝试访问`Object.clone()`方法时遇到错误:"module java.base does not open java.lang to unnamed module",这是因为Java模块系统默认封装了核心模块。以下是系统级的解决方案: #### 1. **标准解决方案(推荐)** 在自定义类中重写`clone()`方法: ```java public class MyClass implements Cloneable { @Override public Object clone() throws CloneNotSupportedException { return super.clone(); // 通过继承访问protected方法 } } ``` 使用方式: ```java MyClass obj = new MyClass(); MyClass copy = (MyClass) obj.clone(); // 正常调用 ``` #### 2. **反射方案(需添加JVM参数)** 如果必须直接访问`Object.clone()`: ```java try { Method cloneMethod = Object.class.getDeclaredMethod("clone"); cloneMethod.setAccessible(true); // 突破访问限制 Object copy = cloneMethod.invoke(originalObj); } catch (Exception e) { e.printStackTrace(); } ``` **必须添加JVM启动参数**: ``` --add-opens java.base/java.lang=ALL-UNNAMED ``` #### 3. **深度克隆替代方案** 使用序列化实现深度克隆(无需访问`clone()`): ```java public static <T extends Serializable> T deepClone(T obj) { try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos)) { oos.writeObject(obj); try (ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis)) { return (T) ois.readObject(); } } catch (Exception e) { throw new RuntimeException("Clone failed", e); } } ``` #### 关键问题分析 | 问题类型 | 原因 | 解决方案 | |----------------------|----------------------------------------------------------------------|------------------------------| | 模块访问限制 | `java.base`模块未向未命名模块开放`java.lang`包 | 使用`--add-opens` JVM参数 | | `protected`访问限制 | `Object.clone()`只能在子类或同包中访问 | 重写`clone()`方法 | | 深度克隆需求 | 默认`clone()`是浅拷贝 | 实现`Serializable`深度克隆 | > **最佳实践**:优先使用重写`clone()`的标准方式,反射方案会破坏模块封装性,应作为最后手段[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值