用Java克隆对象
这样做会调用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(); } }
通过允许实现super.clone()
所有abstract
子类基本上什么都不做(因为你的例子中的所有抽象类都什么都不做)并且只调用(最后) Object.clone()
方法。
我的建议是允许所有具体类(如ASub)覆盖clone方法并使用复制构造函数 idiom来创建自己的精确克隆….
例如
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
克隆
首先,请注意clone()接口已损坏 ,因此不应在新代码中使用。 最好是实现复制构造函数 。
但是,如果您确实需要这样做, TopMost
正确的方法是实现Cloneable
。 为什么? 有效Java第2版,第11项:
那么
Cloneable
做了什么,因为它不包含任何方法? 它确定了Object
的受保护clone
实现的行为:如果一个类实现Cloneable
,则Object
的clone方法返回该对象的逐个字段副本; 否则它会抛出CloneNotSupportedException
。这是一个非常非典型的接口使用,而不是一个被模拟的接口。 通常,实现接口会说明类可以为其客户做些什么。 在Cloneable
的情况下,它修改了超类上受保护方法的行为。
此外, Asub.clone
应该被public
,不受protected
– 否则你不能从外界称呼它。 此外,如果您使用的是Java5或更高版本,则Asub.clone
返回Asub
而非Object
(以及类似的超类)是合法且合乎需要的。
您没有在类中显示任何成员 – 各种类中的clone
实现可能会有很大不同,具体取决于该类中的成员类型。 也就是说,如果一个类有任何可变成员,你需要仔细深度复制所有这些成员,否则最终会有不同的对象共享其内部状态。
但是,假设您的类只有原始字段或不可变字段,克隆按预期工作,尽管您的抽象类中有许多不必要的clone
方法,所有这些方法super.clone()
调用super.clone()
– 您可能最好使用Asub.clone()
只。
作为旁注,如果Top a = (Top) super.clone()
不是拼写错误,则引入从基类到派生类的依赖关系,这不是一个好主意。
对super.clone()
的调用会禁用虚拟机制,因此它只调用Object.clone()