这样做会调用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();
}
}
答案 0 :(得分:3)
首先,请注意 the clone() interface is broken ,因此不应在新代码中使用。最好实现复制构造函数。
但是,如果真的需要这样做,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()
- 你最好只使用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()