Java clone()方法使用new关键字和复制构造函数而不是super.clone()

时间:2013-04-03 15:20:33

标签: java clone copy-constructor deep-copy

在网上搜索如何以多态方式制作对象的深层副本时,我发现solution声称使用clone()方法解决了许多问题,例如克隆final字段是不可能的。该解决方案结合了clone()实现中受保护的复制构造函数的使用,基本上就是这样(从引用页面复制的示例):

public class Person implements Cloneable
{
    private final Brain brain; // brain is final since I do not want 
                               // any transplant on it once created!
    private int age;

    public Person(Brain aBrain, int theAge)
    {
        brain = aBrain; 
        age = theAge;
    }

    protected Person(Person another)
    {
        Brain refBrain = null;
        try
        {
            refBrain = (Brain) another.brain.clone();
            // You can set the brain in the constructor
        }
        catch(CloneNotSupportedException e) {}
        brain = refBrain;
        age = another.age;
    }

    public Object clone()
    {
        return new Person(this);
    }

    …
}

clone()的{​​{1}}方法可能会以类似的方式实施。

基于documentation of the clone() method,这个方法的所有“契约”似乎都不是“绝对要求”,并且“通过调用Brain获得返回的对象”只是一种约定。

那么,这个实现实际上是不正确的吗?为什么呢?

如果它是正确的,为什么它不会成为一种设计模式?这有什么缺点???

谢谢,彼得

3 个答案:

答案 0 :(得分:1)

您尝试通过实现可克隆接口进行克隆,但不遵循建议的克隆合同。

你基本上是使用复制构造函数创建新对象,我的问题是你为什么需要实现cloneable?

如果您正在实施克隆,那么您必须尊重合同。当你在克隆方法中使用复制构造函数时,我不会推荐这种方法,因为它的子类的克隆不会是子类的对象,而且它将成为Person类的一个对象。

另外要指出的是,使用复制构造函数而不是克隆接口是更加面向对象的方法。

答案 1 :(得分:0)

  

那么,这个实现实际上是不正确的吗?为什么呢?

这不安全,因为CloneNotSupportedException被删除。

如果Brain不能克隆,那么新人就没有脑子:) 如果您的对象结构中有一个您无法控制的对象(无法访问源),该怎么办?

  

为什么它没有成为一种设计模式

因为并非所有对象都可以从类似对象中克隆。通常,有一些环境对象可以更好地了解这个特定的新对象的外观,而不是现有的邻居对象。

答案 2 :(得分:0)

此方法的缺点(除了CloneNotSupportedException被删除的事实)是,如果子类调用super.clone(),它们将获得Person的实例而不是它们自己的实例他们可能期望上课。

如果您知道子类不依赖Object.clone()(或者没有子类),那么您的方法就可以了