为什么java.lang.Cloneable不重写java.lang.Object中的clone()方法?

为什么java.lang.Cloneable不重写java.lang.Object中的clone()方法?,java,clone,cloneable,Java,Clone,Cloneable,Java.lang.Cloneable接口的Java规范将自己定义为表示扩展它的任何对象也实现了在Java.lang.object中处于休眠状态的clone()方法。具体来说,它说: 类实现了Cloneable接口,以向java.lang.Object#clone()方法指示该方法为该类的实例创建字段对字段的副本是合法的 对我来说,这意味着应该假设每个扩展了Cloneable的类都有一个public Object clone()方法。这使得我们很容易假设以下方法是有效的: public stat

Java.lang.Cloneable
接口的Java规范将自己定义为表示扩展它的任何对象也实现了在
Java.lang.object
中处于休眠状态的
clone()
方法。具体来说,它说:

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

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

public static makeACloneFrom(Cloneable c)
{
  return c.clone();
}
然而,情况并非如此,因为
可克隆的
源代码(sans-javadoc)的全部都是简单的

package java.lang;

public interface Cloneable {
}
这意味着
Cloneable#clone()
不存在(尝试编译上面的示例方法会引发编译时错误,例如“
找不到symbol:method clone()
”)。
Cloneable
的源代码不应该包含类似于
public Cloneable clone()的内容吗


为什么不允许我们假设实现
Cloneable
的类有一个
公共Cloneable clone()
方法?

,因为它是一个设计糟糕的接口

From(抱歉,Google Books没有第二版的预览版):

第11项:明智地覆盖克隆
Cloneable
接口旨在作为mixin接口(项目 18) 用于发布允许克隆的对象。不幸的是, 它没有达到这一目的。它的主要缺陷是缺少一个
clone
方法和
对象的
clone
方法受到保护。你 借助反射(第53项),无法调用克隆 方法仅因为它实现了
可克隆性
。甚至是 反射调用可能会失败,因为无法保证 对象具有可访问的克隆方法


clone
Cloneable
已损坏,设计糟糕,不应用于新代码中。(见有效Java第11项。)

之所以会出现这种特殊情况,是因为
Cloneable
是一个令人困惑的、神奇的接口,仅仅实现
Cloneable
的行为就可以通过反射改变
对象的行为。有效的Java说:

…如果类实现了
Cloneable
Object
clone
方法返回对象的逐字段副本;否则将抛出CloneNotSupportedException。这是一个非常非典型的接口使用,而不是一个被模仿


可能重复的。。。所以,在Java1.8中,这是一个应该改变的东西?它早就应该改变了。然而,我不认为它会是这样,因为它会引入向后的不兼容性。如果Java 1.8中有一个“修复”,我想它将是一个类似于
@Copyable
注释的东西。@SoboLAN您希望它如何更改?删除它会导致很多兼容性问题,但收效甚微。加上一些设计糟糕、你不应该使用的东西,真的吗?::叹气::虽然我讨厌
Cloneable
clone
,但我宁愿看到它们被弃用,也不愿被彻底删除。尽管如此,Oracle不能完全重构所有Java用户的代码,它的政策是基本上避免不惜一切代价破坏外部代码。我不认为反射与之有任何关系(一方面它早于反射)。哦,天哪,那更邪恶。我猜
clone
的本机实现相当于内部反射?根据Javadoc,“类对象的克隆方法执行特定的克隆操作。首先,如果这个对象的类没有实现接口Cloneable,那么就会抛出CloneNotSupportedException。请注意,所有数组都被视为实现接口可克隆,并且数组类型T[]的克隆方法的返回类型为T[],其中T是任何引用或基元类型。否则,此方法将创建此对象类的新实例,并使用此对象对应字段的内容初始化其所有字段。。。。。。仿佛通过转让;字段的内容本身不是克隆的。因此,此方法执行此对象的“浅拷贝”操作,而不是“深拷贝”操作。“是的,但它必须以本机方式而不是Java方式执行
Cloneable
检查。