Effective Java:分析clone()方法

时间:2012-07-18 11:56:22

标签: java clone cloneable

从Effective Java Item 11(明智地覆盖克隆)中考虑以下内容:Josh Bloch正在解释clone()合同的错误。

  

此合同存在许多问题。 “不”的规定   构造函数被称为“太强大了。一个表现良好的克隆方法可以调用构造函数   创建正在构建的克隆内部的对象。如果是这样的   final,clone甚至可以返回由构造函数创建的对象。

有人可以解释Josh Bloch在第一段中所说的“如果类是finalclone甚至可以返回由构造函数创建的对象。” final在这里与clone()有什么关系?

5 个答案:

答案 0 :(得分:22)

这是因为clone()的典型实现如下所示:

public class MyClass implements Cloneable {
  protected Object clone() {
    MyClass cloned = (MyClass) super.clone();
    // set additional clone properties here
  }
}

通过这种方式,您可以继承超类中的克隆行为。这是广泛的 假设clone()操作的结果将根据调用它的对象返回正确的实例类型。 IE浏览器。 this.getClass()

因此,如果一个类是final,那么您不必担心调用super.clone()的子类并且不会返回正确的对象类型。

public class A implements Cloneable {
    public Object clone() {
       return new A();
    }
}


public class B extends A {
    public Object clone() {
       B b = (B)super.clone(); // <== will throw ClassCastException
    }
}

但是,如果A是最终的,没有人可以扩展它,因此使用构造函数是安全的。

答案 1 :(得分:20)

如果一个类不是final,那么clone必须返回调用它的派生类最多的类。这不适用于构造函数,因为clone不知道要调用哪一个。如果一个类是final,那么它不能有任何子类,所以在克隆时调用它的构造函数没有危险。

答案 2 :(得分:6)

为了可克隆,类不必提供自己的clone实现。它可以将其委托给它的可克隆超类。接下来是:clone必须始终返回与调用它的实例相同的类的实例。如果调用显式构造函数,则无法在所描述的情况下实现。如果课程覆盖clone是最终的,另一方面,这没关系。

答案 3 :(得分:2)

clone的合同规定“按惯例,应通过调用super.clone”获取返回的对象。如果您的类不是final并且您返回通过构造函数调用获得的内容,则从子类调用super.clone()将不会返回预期的结果(首先,返回的对象的类型将不是子类的类型,因为本机clone()方法将返回。)

答案 4 :(得分:1)

见Jorado答案。这是解释。另外克隆在最终字段中有问题,请参阅: http://en.wikipedia.org/wiki/Clone_%28Java_method%29#clone.28.29_and_final_fields

你还应该阅读Josh关于克隆的采访: http://www.artima.com/intv/bloch13.html