我正在阅读正确执行数组的深层副本,但是我对如何#clone()实现它感到困惑.它是java.lang.Object该类的成员,但如果您阅读了javadoc:
首先,如果此对象的类未实现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 {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
为什么Java以这种方式完成它?我确信他们有合理的理由,但我似乎无法弄明白.
Mar*_*nik 21
Java中的克隆契约规定每个clone实现必须首先从中获取克隆实例super.clone().这将创建一个始终以调用结束的链Object.clone,并且该方法包含"神奇的"本机级代码,该代码生成struct表示Java对象的基础raw的二进制副本.如果这个机制不存在,clone就不会是多态的:该Object.clone方法产生一个被调用的类的实例; 没有本机代码就无法再现.
这就是为什么Object.clone不能避免这种方法的原因.Cloneable 可能包含一个clone方法,但它会产生有关该throws条款的问题.它的立场是自由声明clone没有声明的异常,或声明任意异常.如果已在接口中声明该方法,则无法实现此灵活性.
请记住,仿制药将是克隆很少使用的:想象protected T clone()在Object哪里会:T来自哪里?我们是否需要Object<T>并强制Java Universe中的每个类都要对其自身进行参数化,所有这些只是为了使这个半弃用的机制更好地工作?还要记住,此代码完全合法:
public class TheMightyOne implements Cloneable {
@Override public TheMightyOne clone() {
return (TheMightyOne) super.clone();
}
}
Run Code Online (Sandbox Code Playgroud)
你可以称之为:
TheMightyOne one = new TheMightyOne();
TheMightyOne two = one.clone(); // do downcasts needed
Run Code Online (Sandbox Code Playgroud)
为了处理创建克隆和基本字段复制,克隆需要继承一个方法实现。Cloneable 类可以出现在层次结构中的任何位置,并且可能需要扩展特定的超类来完成其主要工作。所有可能的 Cloneable 类都可以继承实现的唯一超类是 Object。
克隆的定义早于泛型。
| 归档时间: |
|
| 查看次数: |
3761 次 |
| 最近记录: |