【问题标题】:Effective Java: Analysis of the clone() method高效Java:clone()方法分析
【发布时间】:2012-07-17 10:54:07
【问题描述】:

考虑以下来自有效 Java 条款 11(明智地覆盖克隆)的内容,其中 Josh Bloch 解释了 clone() 合同的问题。

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

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

【问题讨论】:

    标签: java clone cloneable


    【解决方案1】:

    这是因为 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 是 final 的,没有人可以扩展它,因此使用构造函数是安全的。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        一个类不必提供它自己的clone 实现就可以被克隆。它可以将其委托给它的可克隆超类。问题来了:clone 必须始终返回与调用它的实例相同的类的实例。如果调用显式构造函数,则在所描述的情况下这是不可能实现的。另一方面,如果覆盖 clone 的类是 final 的,那就没问题了。

        【讨论】:

          【解决方案4】:

          clone 的合约规定“按照约定,返回的对象应该通过调用super.clone 来获得”。如果您的类不是最终类,并且您返回通过构造函数调用获得的内容,则从子类调用 super.clone() 将不会返回预期结果(首先,返回对象的类型不会是子类的类型,如原生的clone() 方法会返回)。

          【讨论】:

            【解决方案5】:

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

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

            【讨论】:

              猜你喜欢
              • 2017-12-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-10-27
              • 2016-09-21
              • 2014-04-02
              • 2014-04-28
              相关资源
              最近更新 更多