[英]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.