我知道这clone()
是一个受保护的方法,但“受保护”意味着它可以被特定类的所有子类访问。
任何 Java 类都是 的子类Object
,那么这里的受保护方法的原因是什么?
为什么我们clone()
只能调用实现Cloneable
接口的类?clone()
我不明白它是如何与inObject
被声明为受保护的事实联系起来的。
Object 的 clone() 方法非常特殊,因为它总是返回当前类的一个实例,该实例复制了所有字段(甚至是 final)。我认为用普通的 Java 代码甚至不能用反射来重现它是不可能的。
因此,它必须对所有类都可用,但由于您不希望所有内容都可克隆,因此默认情况下不应从外部调用它,因此必须对其进行保护。
作为附加检查,clone
检查类是否实现Cloneable
,只是为了确保您不会意外克隆不可克隆。
总而言之,克隆有点损坏,因为当您需要深度复制最终字段时它不起作用。我建议您按照这种模式手动实现实例复制。
public class Base {
/** one or more public constructors */
public Base() { ... }
/** copy-constructor */
protected Base(Base src) { /* copy or deep-copy the state */ }
public Base copy() { return new Base(this); }
}
public class Derived extends Base {
/** one or more public constructors */
public Derived() { ... }
/** copy-constructor */
protected Derived(Derived src) {
super(src);
/* copy or deep-copy the state */
}
@Override
public Derived copy() { return new Derived(this); }
}
因为这就是他们设计的方式。在 Bug Parade 的某处有一个声明,设计的最初原因“迷失在时间的迷雾中”,但我记得 Sun 在 1990 年代的讨论中说该设计提供了四种可能的行为。
不记得细节了:-| 但是你可以解决它:
clone()
方法除了派生类之外是不可访问的。Cloneable:
可以克隆实现类,但clone()
除了派生类外,方法不可访问。Cloneable
并提供您自己的clone()
方法:与 (2) 一样,但有可能clone()
公开,现在也可以返回正确的类型。clone()
并抛出NotCloneableException:
你回到 1。放入clone()
界面会失去一些。
的默认实现Object.clone()
是对象中的基类型方法可以生成该对象相同类型的新对象的唯一方法(可能是反射除外)。另一方面,对于许多类,派生类不可能实现clone
不违反基类不变量的工作方法。希望不允许此类派生类调用clone
和接收不可能使用的对象。
回想起来,应该做的正确的事情可能是定义一个CloneableObject
继承自其中的系统,Object
其中包括一个受保护的memberwiseclone
方法(就像Object.clone()
现在一样工作),并且没有其他任何东西,并且让所有可以克隆的类都继承自它作为它们的基础类型。这种类型可以在其clone()
方法中使用一些其他类型无法使用的特殊魔法。然而,系统使用Cloneable
接口的存在来决定是否应该允许对象使用基本级别的clone()
方法。不是一个伟大的设计,但它就是这样。很难说这比允许几乎所有派生类调用的 .NET 方法好还是坏MemberwiseClone
派生类是否有任何方法可以做到这一点而不会产生损坏的对象。
Cloneable 是一个接口,为了克隆对抽象基类的引用,基类必须具有 clone() 方法,或者其父类之一必须具有可公开访问的 clone() 方法。Cloneable 只是充当标记接口。
请参阅:
http://docs.oracle.com/javase/7/docs/api/java/lang/Cloneable.html
一个类实现了 Cloneable 接口,以向 Object.clone() 方法指示该方法可以合法地对该类的实例进行逐个字段的复制。在未实现 Cloneable 接口的实例上调用 Object 的 clone 方法会导致抛出异常 CloneNotSupportedException。
按照惯例,实现此接口的类应使用公共方法覆盖 Object.clone(受保护的)。有关覆盖此方法的详细信息,请参阅 Object.clone()。
请注意,此接口不包含 clone 方法。因此,不可能仅凭借实现该接口的事实来克隆对象。即使以反射方式调用 clone 方法,也不能保证它会成功。
来到你的问题,即使 Object 有受保护的方法clone
Object
没有实现Cloneable
,但是被调用clone()
方法的对象必须实现 Cloneable interface
。