覆盖 Clone 而不调用 super.clone

Vin*_*C M 7 java clone

clone不实现 Cloneable 接口和不调用 super.clone() 的情况下重写方法是否是一个好习惯。这样,CloneNotSupportedException就不会抛出异常。

考虑这个类:

class Money {

    private BigDecimal x ;

    public Object clone() {
        Money m1 = new Money();
        m1.setX(this.x);
        return m1;
    }

    public BigDecimal getX() {
        return x;
    }

    public void setX(BigDecimal x) {
        this.x = x;
    }

}        
Run Code Online (Sandbox Code Playgroud)

这个类不会抛出CloneNotSupportedException,它就像一个复制构造函数。

这是一个好方法吗?

Ale*_*eev 5

您有克隆逻辑,当然您知道您的类支持克隆,因此clone方法不应该抛出CloneNotSupportedException。因此,super.clone()在这里调用会导致您编写样板try/catch块,CloneNotSupportedException其中包含重新抛出AssertionError,这显然永远不会抛出。这个标记Cloneable......我认为,Java 的这一部分设计错误。所以我只是忽略文档并手动复制字段。

使用的唯一两个参数super.clone()是性能(我想,类似于memcpy内部使用的东西)和添加新字段时对错误的持久性。


Ada*_*old 0

在您的情况下,您有一个具有该clone方法的类,但不告诉外界它实际上是Cloneable。这不叫克隆,而是原型设计。

如果不想clone使用该接口,请选择其他方法名称。

请同时检查文档:

创建并返回该对象的副本。“复制”的精确含义可能取决于对象的类。一般意图是,对于任何对象 x,表达式: x.clone() != x 将为 true,并且表达式: x.clone().getClass() == x.getClass() 将为 true ,但这些并不是绝对的要求。虽然通常情况是: x.clone().equals(x) 将为 true,但这不是绝对要求。按照惯例,返回的对象应该通过调用 super.clone 来获取。如果一个类及其所有超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass() 的情况将会出现。

您必须打电话是有原因的super.clone()