Java:为什么为继承设计的类应该包含受保护的克隆方法?

Java:为什么为继承设计的类应该包含受保护的克隆方法?,java,cloning,effective-java,Java,Cloning,Effective Java,我正在仔细阅读Joshua Bloch的《高效Java》,我发现了以下关于克隆的句子: 如果为继承设计类,请注意,如果选择不提供行为良好的受保护克隆方法,子类将无法实现可克隆性 我有点困惑,因为在我的小测试中: public class Cloning { public static void main(String[] args) throws CloneNotSupportedException { Woman woman1 = new Woman("Marie

我正在仔细阅读Joshua Bloch的《高效Java》,我发现了以下关于克隆的句子:

如果为继承设计类,请注意,如果选择不提供行为良好的受保护克隆方法,子类将无法实现可克隆性

我有点困惑,因为在我的小测试中:

public class Cloning {

    public static void main(String[] args) throws CloneNotSupportedException {

        Woman woman1 = new Woman("Marie Curie-Sklodowska", 33, "Physics");
        Woman woman2 = (Woman) woman1.clone();
    }

    static abstract class Person {
        protected String name;
        protected int age;

        Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }

    static class Woman extends Person implements Cloneable {

        private String field;

        Woman(String name, int age, String field) {
            super(name, age);
            this.field = field;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
}
我没有得到任何错误。我想,我没有正确理解这个句子。有人能解释一下作者的想法吗

如果为继承设计类,请注意,如果选择不提供行为良好的受保护的
clone()
方法,子类将无法实现
Cloneable

他错了。他们可以。考虑:

public class A
{
    private int fieldA;
}

public class B extends A implements Cloneable
{
    public B clone() throws CloneNotSupportedException
    {
        return (B)super.clone();
    }
}
B.clone
()将返回调用它的
B
实例的完美副本,包括
a.fieldA
。反例反驳:QED

[我知道这个
clone()
实际上不应该声明为抛出
CloneNotSupportedException
,但它使演示更简单。]

这一切都很奇怪,因为他刚才说了两句话:

有些程序员只是选择从不重写
clone()
方法

为继承而设计的类不应实现它[
Cloneable
]

更奇怪的是,上面的第一句话是整个章节的最后一句话,完全没有论据或例子的支持,除非整个章节都是为了证明这一点,而事实并非如此。整个章节都很混乱,很难弄清楚到底是什么在索赔。克隆并不像他说的那么难理解或实现。这也不重要。在Java的20年里,我没有在严肃的代码中使用过它,也没有在所谓的“复制构造函数”中使用过它

如果为继承设计类,请注意,如果选择不提供行为良好的受保护的
clone()
方法,子类将无法实现
Cloneable

他错了。他们可以。考虑:

public class A
{
    private int fieldA;
}

public class B extends A implements Cloneable
{
    public B clone() throws CloneNotSupportedException
    {
        return (B)super.clone();
    }
}
B.clone
()将返回调用它的
B
实例的完美副本,包括
a.fieldA
。反例反驳:QED

[我知道这个
clone()
实际上不应该声明为抛出
CloneNotSupportedException
,但它使演示更简单。]

这一切都很奇怪,因为他刚才说了两句话:

有些程序员只是选择从不重写
clone()
方法

为继承而设计的类不应实现它[
Cloneable
]


更奇怪的是,上面的第一句话是整个章节的最后一句话,完全没有论据或例子的支持,除非整个章节都是为了证明这一点,而事实并非如此。整个章节都很混乱,很难弄清楚到底是什么在索赔。克隆并不像他说的那么难理解或实现。这也不重要。在Java的20年里,我没有在严肃的代码中使用过它,也没有在所谓的“复制构造函数”中使用过它。

重写
Person.clone()
并使其显式抛出
CloneNotSupportedException
。然后它就不起作用了。@AndyTurner这听起来更像是选择提供一个行为不端的
clone
方法。@AndyTurner这个问题显然是重复的,但我根本没有得到答案。据我所知,
clone()
可以很好地处理超类中的私有字段。嗯,我正在阅读关于同一主题的文章,但我也不清楚接受的答案。它说,创建私有字段“违背了承诺”,但我尝试过使用私有字段,但没有任何区别。克隆的对象是相同的。因此,我的问题可能是克隆,但原始问题没有令人满意的答案。我重新打开该问题,因为我不相信答案令人满意。重写
Person.clone()
,并使其显式抛出
CloneNotSupportedException
。然后它就不起作用了。@AndyTurner这听起来更像是选择提供一个行为不端的
clone
方法。@AndyTurner这个问题显然是重复的,但我根本没有得到答案。据我所知,
clone()
可以很好地处理超类中的私有字段。嗯,我正在阅读关于同一主题的文章,但我也不清楚接受的答案。它说,创建私有字段“违背了承诺”,但我尝试过使用私有字段,但没有任何区别。克隆的对象是相同的。因此,我的问题可能是克隆,但原始的问题没有令人满意的答案。我重新打开这个问题,因为我认为答案不令人满意。我原以为克隆部分的摘要有问题。但我认为它达到了它的目标——我对使用
clone()
方法和
Cloneable
界面感到非常气馁。谢谢你的回答!我原以为克隆部分的摘要有问题。但我认为它达到了它的目标——我对使用
clone()
方法和
Cloneable
界面感到非常气馁。谢谢你的回答!