简体   繁体   English

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

[英]Cloning objects in Java [3 questions]

will the clone method of Asub be called by doing this? 这样会调用Asub的clone方法吗? Or is Asub deep cloned properly? 还是正确克隆了Asub? If not, is there a way to propery deep clone Asub through this kind of method? 如果没有,是否有办法通过这种方法对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();
    }
}

First of all, note that the clone() interface is broken , thus should not be used in new code. 首先,请注意clone()接口已损坏 ,因此不应在新代码中使用。 It is better to implement copy constructor(s) instead . 最好改为实现复制构造函数

However, if you really need to do it, the proper way is for TopMost to implement Cloneable . 但是,如果您确实需要这样做,则正确的方法是让TopMost实现Cloneable Why? 为什么? Says Effective Java 2nd Edition, Item 11: 说有效的Java 2nd Edition,第11项:

So what does Cloneable do, given that it contains no methods? 那么,鉴于Cloneable不包含任何方法,该怎么办? It determines the behavior of Object 's protected clone implementation: if a class implements Cloneable , Object 's clone method returns a field-by-field copy of the object; 它确定Object的受保护clone实现的行为:如果一个类实现Cloneable ,则Object的clone方法返回该对象的逐字段副本; otherwise it throws CloneNotSupportedException .This is a highly atypical use of interfaces and not one to be emulated. 否则会抛出CloneNotSupportedException 。这是一种非常不典型的接口用法,而不是要模拟的接口。 Normally, implementing an interface says something about what a class can do for its clients. 通常,实现接口会说明类可以为其客户端执行的操作。 In the case of Cloneable , it modifies the behavior of a protected method on a superclass. Cloneable的情况下,它会修改超类上受保护方法的行为。

Moreover, Asub.clone should be declared public , not protected - otherwise you can't call it from the outside world. 此外,应该将Asub.clone声明为public ,而不是protected -否则您将无法从外部调用它。 Also, if you are using Java5 or above, it is legal and desirable for Asub.clone to return Asub , not Object (and similarly for its superclasses). 另外,如果您使用的是Java5或更高版本,则Asub.clone返回Asub而不是Object (以及其超类类似)也是合法且合乎需要的。

You don't show any members in the classes - the implementations of clone in the various classes can be a whole lot different depending on the types of members in that class. 您没有在类中显示任何成员-各个类中clone的实现可能完全不同,具体取决于该类中成员的类型。 Namely, if a class has any mutable members, you need to carefully deep copy all of them, otherwise you end up with distinct objects sharing their internal state. 即,如果一个类具有任何可变成员,则需要仔细地深度复制所有成员,否则最终将得到共享其内部状态的不同对象。

However, supposing your classes have only primitive or immutable fields, the cloning works as expected, although you have a lot of unnecessary clone methods in your abstract classes, all of which simply call super.clone() - you may be better off with Asub.clone() only. 但是,假设您的类仅具有原始或不可变字段,尽管您的抽象类中有很多不必要的clone方法,所有这些clone方法都只需调用super.clone()即可进行克隆,所以克隆可以按预期工作-使用Asub.clone()可能会更好Asub.clone()仅。

As a side note, if Top a = (Top) super.clone() is not a typo, you introduce a dependency from base class to derived class, which is not a good idea. 附带说明一下,如果Top a = (Top) super.clone()不是拼写错误,那么您将引入从基类到派生类的依赖关系,这不是一个好主意。

By allowing all abstract subclasses implementing super.clone() essentially does nothing (since all your abstract classes in your example are doing nothing) and just call (at the end) Object.clone() method. 通过允许所有abstract子类实现super.clone()本质上什么都不做(因为示例中的所有抽象类什么都不做),而只需调用(最后) Object.clone()方法。

My suggestion is to allow all concrete classes (like ASub) to override the clone method and use the copy constructor idiom to create an exact clone of itself.... 我的建议是允许所有具体的类(如ASub)重写clone方法,并使用复制构造函数惯用法来创建其自身的精确克隆。

eg 例如

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 Make TopMost Cloneable PS使TopMost 克隆

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM