You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何无法在子类中访问Object类的protected方法clone()?

为什么无法直接调用Object类的protected clone()方法?

这是个非常典型的Java访问权限误区,很多刚接触克隆机制的开发者都会碰到这个问题,我来给你把底层逻辑讲透:

先搞懂protected权限的真实规则

你可能误以为「子类可以随便访问父类的protected方法」,但Java对protected的权限控制其实有更细的限制:

  • 你可以访问自己实例中继承自父类的protected方法
  • 同包类可以访问任何同包实例的protected方法
  • 但不同包的子类,或者非子类的同包类,不能通过其他子类的实例去访问父类的protected方法

回到你的代码场景:

  • Test类和Test2类是同包,但Test不是Test2的子类
  • 你在Test的main方法里,调用的是Test2实例的clone()方法——这个方法本质是Object类的protected方法
  • 对于Test来说,它虽然是Object的子类,但它只能调用自己实例的clone(),不能调用另一个Object子类(Test2)实例的clone(),因为跨了实例所属的子类类型,权限不允许

为什么实现Cloneable还不够?

Cloneable只是一个标记接口,它的作用仅仅是告诉Object的clone()方法:「这个类允许被克隆」,如果没有实现它,调用clone()会抛出CloneNotSupportedException。但它完全不会改变clone()方法的访问权限——Object的clone()依然是protected。

解决方法

方法1:在Test2中重写clone()并改为public

这是最标准的做法,重写后对外开放克隆能力:

class Test2 implements Cloneable {
    @Override
    public Object clone() throws CloneNotSupportedException {
        // 调用父类的clone实现
        return super.clone();
    }
}

然后在Test类中调用时需要处理异常(要么main方法加throws CloneNotSupportedException,要么用try-catch包裹):

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Test2 c1 = new Test2();
        Test2 c2 = (Test2) c1.clone(); // 现在可以正常调用了
    }
}

方法2:提供自定义的克隆方法(封装clone())

如果不想把clone()暴露为public,可以在Test2里写一个自定义的public方法,内部调用clone():

class Test2 implements Cloneable {
    public Test2 createCopy() throws CloneNotSupportedException {
        return (Test2) this.clone();
    }
}

然后Test类里调用这个方法:

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Test2 c1 = new Test2();
        Test2 c2 = c1.createCopy();
    }
}

内容的提问来源于stack exchange,提问作者Denys_newbie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 16:17:50