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()
方法?
答案 0 :(得分:6)
唉。 clone
和Cloneable
已损坏,设计非常严格,不应在新代码中使用。 (参见Effective Java item 11。)
这个特殊事情的原因是Cloneable
是一个容易混淆的,神奇的界面,因此仅仅实施Cloneable
的行为会改变Object.clone
的反射行为。有效的Java说:
...如果一个类实现
Cloneable
,Object
的{{1}}方法返回该对象的逐个字段副本;否则会抛出CloneNotSupportedException。这是一种非常非典型的接口使用,而不是一个被模仿的......
答案 1 :(得分:5)
因为它是一个设计不佳的界面。
来自Effective Java(抱歉,Google图书没有第2版的预览版):
第11项:明智地覆盖
clone
Cloneable
界面用作 mixin界面(Item 18)对象宣传他们允许克隆。不幸, 它无法达到这个目的。它的主要缺陷是缺乏一个clone
方法,Object
的{{1}}方法受到保护。您 不能,借助反射(第53项),调用clone
对象上的方法仅仅因为它实现了clone
。甚至一个 反思性调用可能会失败,因为无法保证 对象具有可访问的Cloneable
方法。