用Java克隆对象[3个问题]

时间:2010-09-06 15:56:11

标签: java class abstract-class clone

这样做会调用Asub的clone方法吗?或Asub是否正确克隆?如果没有,有没有办法通过这种方法推动深度克隆Asub?

abstract class Top extends TopMost {
    protected Object clone() {
        Object obj = super.clone();
        // deep copy and try catch
    }


}

abstract class A extends Top { 
    protected Object clone() {
        Object obj = super.clone();
       // deep copy and try catch
    } 


}

class Asub extends A {
    protected Object clone() {
        Object obj = super.clone();
        // deep copy and try catch
    }

    public void doSomethingNew() {
    }
}

abstract class TopMost {
    public void someMethod() {
        Top a = (Top) super.clone();
        // more code here
    }
}

public class Main {
    public static void main(String... args) {
        Asub class1 = new Asub();
        class1.someMethod();
    }
}

3 个答案:

答案 0 :(得分:3)

首先,请注意 the clone() interface is broken ,因此不应在新代码中使用。最好实现复制构造函数

但是,如果真的需要这样做,TopMost正确的方法是Cloneable。为什么?有效Java第2版,第11项:

  

那么Cloneable做了什么,因为它不包含任何方法?它决定了   Object的受保护clone实现的行为:如果一个类实现   CloneableObject的clone方法返回对象的逐个字段副本;   否则它会抛出CloneNotSupportedException。这是一种非常不典型的用法   接口而不是模拟的接口。通常,实现一个接口   说一下班级可以为客户做些什么。在Cloneable的情况下,   它修改了超类上受保护方法的行为。

此外,Asub.clone应声明public,而不是protected - 否则您无法从外部世界调用它。此外,如果您使用的是Java5或更高版本,那么Asub.clone返回Asub而不是Object(以及类似的超类)是合法且合乎需要的。

您不会在类中显示任何成员 - 各个类中clone的实现可能会有很大不同,具体取决于该类中的成员类型。也就是说,如果一个类有任何可变成员,你需要仔细深度复制所有这些成员,否则你最终会得到分享其内部状态的不同对象。

但是,假设您的类只有原始字段或不可变字段,克隆按预期工作,尽管您的抽象类中有许多不必要的clone方法,所有这些方法都只调用super.clone() - 你最好只使用Asub.clone()

作为旁注,如果Top a = (Top) super.clone()不是拼写错误,则引入从基类到派生类的依赖关系,这不是一个好主意。

答案 1 :(得分:1)

通过允许实现abstract的所有super.clone()子类基本上什么都不做(因为你的例子中的所有抽象类都什么都不做)并且只调用(最后)Object.clone()方法。 / p>

我的建议是允许所有具体类(如ASub)覆盖克隆方法并使用copy constructor成语创建自己的精确克隆....

e.g。

public abstract class TopMost {

    public TopMost(TopMost rhs) {

    }

}

public abstract class Top extends TopMost {

    public Top(Top rhs) {
        super(rhs);

        //whatever you need from rhs that only is visible from top
    }
}

public abstract class A extends Top { 

    public A (A rhs) {
        super(rhs);

        //TODO: do rhs copy
    }
}

public class ASub extends A {

    public ASub(ASub rhs) {
        super(rhs);

        //TODO: copy other stuff here....
    }

    public Object clone() {
        return new ASub(this);
    }
}

PS TopMost 可克隆

答案 2 :(得分:0)

super.clone()的调用会禁用虚拟机制,因此只会调用Object.clone()