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

用Java克隆对象[3个问题],java,class,abstract-class,clone,Java,Class,Abstract Class,Clone,这样做会调用Asub的克隆方法吗?或者Asub深度克隆是否正确?如果没有,有没有办法通过这种方法实现Asub的深度克隆 abstract class Top extends TopMost { protected Object clone() { Object obj = super.clone(); // deep copy and try catch } } abstract class A extends Top { prot

这样做会调用Asub的克隆方法吗?或者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();
    }
}

首先,请注意,,因此不应在新代码中使用。最好是实现复制构造函数

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

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

此外,
Asub.clone
应该声明为
public
,而不是
protected
——否则您不能从外部世界调用它。另外,如果您使用的是Java5或更高版本,那么
Asub.clone
返回
Asub
,而不是
对象(同样地,它的超类也是如此)是合法且可取的

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

但是,假设您的类只有基本字段或不可变字段,那么克隆工作与预期的一样,尽管您的抽象类中有许多不必要的
clone
方法,所有这些方法都只需调用
super.clone()
——您最好只使用
Asub.clone()


作为旁注,如果
Top a=(Top)super.clone()
不是一个打字错误,那么将从基类到派生类引入一个依赖项,这不是一个好主意。

首先,请注意,因此不应在新代码中使用。最好是实现复制构造函数

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

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

此外,
Asub.clone
应该声明为
public
,而不是
protected
——否则您不能从外部世界调用它。另外,如果您使用的是Java5或更高版本,那么
Asub.clone
返回
Asub
,而不是
对象(同样地,它的超类也是如此)是合法且可取的

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

但是,假设您的类只有基本字段或不可变字段,那么克隆工作与预期的一样,尽管您的抽象类中有许多不必要的
clone
方法,所有这些方法都只需调用
super.clone()
——您最好只使用
Asub.clone()


作为旁注,如果
Top a=(Top)super.clone()
不是一个打字错误,那么将从基类到派生类引入一个依赖项,这不是一个好主意。

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

,方法是允许所有
abstract
子类实现
super.clone()

我的建议是允许所有具体类(如ASub)重写clone方法,并使用该习惯用法创建自身的精确克隆

e、 g


PS通过允许所有
抽象
子类实现
super.clone()
基本上什么都不做(因为示例中的所有抽象类什么都不做),只需调用(最后)
Object.clone()
方法,就可以使
最顶层的
可克隆

我的建议是允许所有具体类(如ASub)重写clone方法,并使用该习惯用法创建自身的精确克隆

e、 g


PSMake
top
Cloneable

是和
可能
不是因为
Cloneable
只是一个标记接口。@不幸的是,精英绅士
Cloneable
不仅仅是一个标记接口。请参阅我的更新。@Péter Török,s
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);
    }
}