繁体   English   中英

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

[英]Why is #clone() not in the Cloneable interface?

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

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

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

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

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

class TypeSafeFoo implements Cloneable<TypeSafeFoo> { // 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而没有声明的异常,或者声明任意异常。 如果已在接口中声明该方法,则无法实现此灵活性。

请记住,Generics对于克隆几乎没用:想象一下Object protected T clone()T来自何处? 我们是否需要Object<T>并强制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

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

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

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

@SuppressWarnings("unchecked")
public static <T extends Cloneable> 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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM