对象中的方法 clone() 不可见?

Posted

技术标签:

【中文标题】对象中的方法 clone() 不可见?【英文标题】:The method clone() from object is not visible? 【发布时间】:2011-07-04 05:29:14 【问题描述】:

问题:

package GoodQuestions;
public class MyClass   
    MyClass() throws CloneNotSupportedException 
        try 
            throw new CloneNotSupportedException();
         catch(Exception e) 
            e.printStackTrace();
        
       

    public static void main(String[] args)     
        try 
            MyClass  obj = new MyClass();
            MyClass obj3 = (MyClass)obj.clone();            
         catch (CloneNotSupportedException e) 
            e.printStackTrace();
        
    

这里的类'MyClass'可以通过调用'Object'类中的clone方法来克隆它自己的对象。 当我尝试在同一个包 'GoodQuestions' 中的另一个类('TestSingleTon')中克隆此类('MyClass')时,它会引发以下编译时错误。

'Object类型的clone()方法不可见'

所以这里是它抛出上述错误的代码?

package GoodQuestions;
public class TestSingleTon 
    public static void main(String[] args) 
        MyClass  obj = new MyClass();
        MyClass obj3 = obj.clone(); ---> here is the compile error.
    

【问题讨论】:

【参考方案1】:

clone() 具有受保护的访问权限。将此添加到MyClass

public Object clone()  
    try  
        return super.clone();  
    catch(Exception e) 
        return null; 
    

也改为public class MyClass implements Cloneable

【讨论】:

我假设受保护的修饰符意味着包级别以及子类。 Java中的每个类不都是Object的子类吗?你的回答是对的,所以我在这里误解了什么? @Justin:是的,它意味着包级别以及子类。所以在你的子类“MyClass”中,它是可见的。但它对“TestSingleTon”不可见,它既不是同一个包也不是子类。 @KarthikBose 因此,这意味着同一子类对象可以在子类中调用受保护的方法。在任何子类中,我们不能用其他子类对象来调用它,例如在这种情况下 clone() 是由 TestSingleton 中的 MyClass 对象调用的? @KarthikBose 因此,来自link 声明“受保护的修饰符指定该成员只能在其自己的包中访问(与包私有一样),此外,还可以通过它的类在另一个包中。”需要更多澄清说明。 在一个类中,如果我在主对象内创建 o = new Object(); o.clone();如果我在我的班级中也覆盖了 clone(),那么 clone() 是不可见的,我得到了【参考方案2】:

发生此错误是因为在 Object 类中 clone() 方法受到保护。 所以你必须在各自的类中覆盖 clone() 方法。 例如。在 MyClass 中添加以下代码

@Override
protected Object clone() throws CloneNotSupportedException 

    return super.clone();

还实现了 Cloneable 接口。 例如。 public class MyClass implements Cloneable

【讨论】:

小心 return super.clone() 可能不够【参考方案3】:

因为 clone() 是一个受保护的方法。详情请见Object.clone()。

重写 MyClass 中的 clone() 并使该类实现 Cloneable 接口。

【讨论】:

【参考方案4】:

微妙之处在于MyClassclone()方法是继承的,而不是在MyClass中定义的。所以MyClass 可以调用对象的clone(),因为它是受保护的,但是MyClass 本身并没有真正拥有 clone(),所以@987654328 @ 无法访问 MyClassclone(),因为没有 clone() 方法。尽管它们都在同一个包中,但您需要在MyClass 中定义一个clone() 方法以确保它确实“具有”clone()。对了,别忘了为MyClass实现接口Cloneable

【讨论】:

【参考方案5】:

Object.clone() 方法具有受保护的访问权限,即it's visible to sub-classes and classes in the same package

最好有一个复制构造函数来手动复制对象。

/**
    Deep copy all the information from other to this
*/
public MyClass (MyClass  other) 
     this.id = other.id;

阅读Why a copy constructor from Josh Bloch

【讨论】:

【参考方案6】:

你只需要让 MyClass 实现 Cloneable 接口。无需为 clone() 提供实现。

【讨论】:

问题与Cloneable 无关,如果您希望clone() 成为public 方法(这就是问题 的实际意义),你确实必须提供你自己的实现。【参考方案7】:

为了让你能够克隆 MyClass,它必须实现 Cloneable 接口

【讨论】:

这不能回答问题。问题中的示例已经实现了 Cloneable。它询问由于clone()protected 方法而导致的编译错误。【参考方案8】:

我对此做了一些测试代码,这是我的发现:

当一个受保护的成员被跨包继承时,它成为继承类的私有成员

当一个受保护的成员在同一个包中被继承时,它成为被继承类的默认成员。

在您的示例中,来自 Object 类的 clone() 跨包继承到 MyClass 中。 对象类在 java.lang 包中,MyClass 在 GoodQuestions 包中。 所以 clone() 方法成为 MyClass 类的私有成员。

这解释了为什么您无法从 TestSingleTon 类访问 clone() 方法。

【讨论】:

我不认为你的理论是正确的。我做了以下事情:- 1) 创建了名为 Parent 的类,使用名为 callProtected() 的受保护方法 2) 在名为 Person 的不同包中创建了另一个类,它扩展了 Parent 类 3) 在同一个名为 Student 的 Person 类包中创建了另一个类extends Person 所以,根据你的理论,如果不同包中的受保护成员变为私有,那么我不应该能够访问 Student 类中的 callProtected 方法,但不幸的是,我可以访问 callProtected 方法。

以上是关于对象中的方法 clone() 不可见?的主要内容,如果未能解决你的问题,请参考以下文章

什么决定了 Java 中的组件可见性?

Java中的修饰符及其作用

使用 mootools 查找 DOM 对象是不是可见的最佳方法 [关闭]

面向对象语言成员变量方法可见性在继承中的变化

Java中同步的可见性效果

cocos2d中的可见性检测