如何正确覆盖克隆方法?

2022-08-31 08:55:12

我需要在我的一个对象中实现一个深度克隆,它没有超类。

处理超类抛出的检查的最佳方法是什么(即)?CloneNotSupportedExceptionObject

一位同事建议我通过以下方式处理它:

@Override
public MyObject clone()
{
    MyObject foo;
    try
    {
        foo = (MyObject) super.clone();
    }
    catch (CloneNotSupportedException e)
    {
        throw new Error();
    }

    // Deep clone member fields here

    return foo;
}

这对我来说似乎是一个很好的解决方案,但我想把它扔给StackOverflow社区,看看我是否可以包括任何其他见解。谢谢!


答案 1

你一定要用吗?大多数人都同意Java已经坏了。cloneclone

Josh Bloch 谈设计 - 复制构造函数与克隆

如果你读过我书中关于克隆的文章,特别是如果你在字里行间阅读,你就会知道我认为已经深深地破碎了。[...]这是一种被打破的耻辱,但它发生了。cloneCloneable

您可以在他的书《Effective Java 2nd Edition, Item 11: Override clone byjuly》中阅读更多关于该主题的讨论。他建议改用复制构造函数或复制工厂。

他接着写了一页又一页的关于如果你觉得你必须如何实现。但他以这样的结尾:clone

所有这些复杂性真的有必要吗?很少。如果扩展一个实现 的类,你别无选择,只能实现一个行为良好的方法。否则,您最好提供对象复制的替代方法,或者干脆不提供该功能Cloneableclone

重点是他的,不是我的。


既然您明确表示别无选择,只能实现 ,因此在这种情况下您可以执行以下操作:确保 .如果是这种情况,那么您可以保证永远不会抓住.正如一些人所建议的那样投掷似乎是合理的,但您也可以添加一个注释,解释为什么在这种特殊情况下永远不会输入捕获块。cloneMyObject extends java.lang.Object implements java.lang.CloneableCloneNotSupportedExceptionAssertionError


或者,正如其他人也建议的那样,您也许可以在不调用 的情况下实现。clonesuper.clone


答案 2

有时实现复制构造函数更简单:

public MyObject (MyObject toClone) {
}

它为您节省了处理的麻烦,适用于字段,您不必担心要返回的类型。CloneNotSupportedExceptionfinal