高效Java:clone()方法分析

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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

【讨论】:

以上是关于高效Java:clone()方法分析的主要内容,如果未能解决你的问题,请参考以下文章

java高效线程池运用以及原理分析

java高效线程池运用以及原理分析

java高效线程池运用以及原理分析

Object源码分析

问题解决方案git clone失败的分析和解决

几种高效电路分析方法