为什么java.lang.Cloneable不会覆盖java.lang.Object中的clone()方法?

时间:2012-04-02 18:29:54

标签: java clone cloneable

java.lang.Cloneable接口的Java规范将自身定义为表示扩展它的任何对象也实现了clone()方法,该方法在java.lang.Object内休眠。具体来说,它说:

  

一个类实现Cloneable接口,以向java.lang.Object#clone()方法指示该方法合法地为该类的实例创建一个字段的副本。

对我来说,这意味着应该假设每个扩展Cloneable的类都有一个public Object clone()方法。这使得很容易假设以下是有效的方法:

public static makeACloneFrom(Cloneable c)
{
  return c.clone();
}

然而,事实并非如此,因为整个Cloneable源代码(sans javadoc)只是

package java.lang;

public interface Cloneable {
}

这意味着Cloneable#clone()不存在(并且尝试编译上面的示例方法会引发类似“cannot find symbol: method clone()”的编译时错误。 Cloneable的源代码不应包含public Cloneable clone();的效果吗?

为什么我们不允许假设实现Cloneable的类具有public Cloneable clone()方法?

2 个答案:

答案 0 :(得分:6)

唉。 cloneCloneable已损坏,设计非常严格,不应在新代码中使用。 (参见Effective Java item 11。)

这个特殊事情的原因是Cloneable是一个容易混淆的,神奇的界面,因此仅仅实施Cloneable的行为会改变Object.clone的反射行为。有效的Java说:

  

...如果一个类实现CloneableObject的{​​{1}}方法返回该对象的逐个字段副本;否则会抛出CloneNotSupportedException。这是一种非常非典型的接口使用,而不是一个被模仿的......

答案 1 :(得分:5)

因为它是一个设计不佳的界面。

来自Effective Java(抱歉,Google图书没有第2版的预览版):

  

第11项:明智地覆盖clone

     

Cloneable界面用作 mixin界面(Item   18)对象宣传他们允许克隆。不幸,   它无法达到这个目的。它的主要缺陷是缺乏一个   clone方法,Object的{​​{1}}方法受到保护。您   不能,借助反射(第53项),调用clone   对象上的方法仅仅因为它实现了clone。甚至一个   反思性调用可能会失败,因为无法保证   对象具有可访问的Cloneable方法。