高效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 甚至可以返回一个构造函数创建的对象。
有人可以通过“如果类是final
,clone
甚至可以返回由构造函数创建的对象”来解释 Josh Bloch 在第一段中所说的话。这里的final
和clone()
有什么关系?
【问题讨论】:
【参考方案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()方法分析的主要内容,如果未能解决你的问题,请参考以下文章