为什么#clone()不在Cloneable接口中?

我正在阅读正确执行数组的深层副本,但是我对#clone()的实现方式感到困惑。 它是java.lang.Object类的成员,但是如果你读了javadocs:

首先,如果此对象的类未实现Cloneable接口,则抛出CloneNotSupportedException。

那么为什么要首先在那里定义clone方法呢? 当然,如果方法只能在存在接口时使用,则将该方法放在接口中。 Cloneable接口本身是空的; 它只是Java使用的标记接口,以确保使用clone方法是合法的。

这样做也会消除使用generics来确保类型安全的能力:

 class Foo implements Cloneable { // Valid. @Override public Object clone() throws CloneNotSupportedException { // ... } } class TypeSafeFoo implements Cloneable { // Not valid. @Override public TypeSafeFoo clone() throws CloneNotSupportedException { // ... } } 

Java为什么这样做? 我确信他们有合理的理由,但我似乎无法弄明白。

Java中的克隆契约规定每个clone实现必须首先从super.clone()获取克隆的实例。 这将创建一个始终以对Object.clone调用结束的链,并且该方法包含“神奇的”本机级代码,该代码生成表示Java对象的基础原始struct的二进制副本。 如果这个机制不存在,那么clone就不会是多态的: Object.clone方法生成一个被调用的类的实例; 没有本机代码就无法再现。

这就是为什么无法避免使用Object.clone方法的原因。 Cloneable 可能包含clone方法,但它会产生有关throws子句的问题。 它的立场是自由声明clone没有声明的exception,或声明任意exception。 如果已在接口中声明该方法,则无法实现此灵活性。

请记住,Generics对于克隆几乎没用:想象一下Object protected T clone()T来自何处? 我们是否需要Object并强制Java Universe中的每个类自身进行参数化,而这一切只是为了使这个半弃用的机制更好地工作? 还要记住,此代码完全合法:

 public class TheMightyOne implements Cloneable { @Override public TheMightyOne clone() { return (TheMightyOne) super.clone(); } } 

你可以称之为:

 TheMightyOne one = new TheMightyOne(); TheMightyOne two = one.clone(); // do downcasts needed 

要处理创建克隆和基本字段复制,克隆需要inheritance方法实现。 Cloneable类可以出现在层次结构中的任何位置,并且可能需要扩展特定的超类来执行其主要作业。 所有可能的Cloneable类都可以inheritance实现的唯一超类是Object。

克隆是在仿制药之前定义的。

clone()方法是不必要的,每个对象都可以通过reflection调用Object.clone方法,因此可以克隆的对象取决于是否实现Cloneable接口。 这是出于安全原因。 您可以通过此util简单地克隆实现Cloneable的对象:

 @SuppressWarnings("unchecked") public static  T clone(Cloneable obj) { T rtn = null; try { Method method = Object.class.getDeclaredMethod("clone"); method.setAccessible(true); rtn = (T) method.invoke(obj); } catch (Throwable t) { t.printStackTrace(); } return rtn; }