我知道clone()
是受保护的方法,但“受保护”意味着它可以被特定类的所有子类访问。
任何Java类都是Object
的子类,那么受保护方法的原因是什么?
为什么我们只能在实现clone()
接口的类上调用Cloneable
?
我无法理解它与clone()
中Object
被声明为受保护的事实有什么联系。
答案 0 :(得分:11)
Object的clone()方法非常特殊,因为它总是返回当前类的一个实例,它复制了所有字段(甚至是最终的)。我不认为用普通的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); }
}
答案 1 :(得分:4)
因为这是他们设计它的方式。在Bug Parade的某个地方有一个声明,设计的最初原因是“迷失在时间的迷雾中”,但我记得Sun在20世纪90年代的一次讨论中说设计给出了四种可能的行为。
不记得细节: - |但你可以解决这个问题:
clone()
方法不可访问。Cloneable:
可以克隆类,但除派生类外,clone()
方法不可访问。Cloneable
并提供您自己的clone()
方法:as(2)但是有可能使clone()
公开,现在也可以返回正确的类型。clone()
,然后抛出NotCloneableException:
,您将回到1。将clone()
放入界面会失去一些。
答案 2 :(得分:3)
Object.clone()
的默认实现是唯一的方法(除了可能是Reflection),通过该方法,对象中的基类型方法可以生成该对象的相同类型的新对象。另一方面,有许多类,派生类不可能实现不违反基类不变量的工作clone
方法。希望不允许这样的派生类调用clone
并接收一个无法使用的对象。
回想起来,正确的做法可能是定义一个继承自CloneableObject
的{{1}}系统,其中包含一个受保护的Object
方法(类似于memberwiseclone
现在没有其他任何东西,并且所有可克隆的类都继承自它作为它们的基类型。该类型可以在其Object.clone()
方法中使用其他类型无法使用的特殊魔法。但是,系统使用clone()
接口的存在来决定是否允许对象使用基级Cloneable
方法。不是一个伟大的设计,但它是它的本质。很难说是否比允许几乎所有派生类调用clone()
的.NET方法更好或更差,无论派生类是否有任何方式可以这样做而不会产生破坏的对象。
答案 3 :(得分:2)
Cloneable是一个接口,为了克隆对抽象基类的引用,基类必须具有clone()方法,或者其父类之一必须具有可公开访问的clone()方法。 Cloneable只是一个标记界面。
请参阅:
答案 4 :(得分:1)
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
未实现Cloneable
,仍然会出现您的问题,但被称为clone()
方法的对象必须实现Cloneable {{1 }}
答案 5 :(得分:-1)
克隆是marker interface。 clone()方法未由Cloneable接口定义。
Object类中的clone方法受到保护,以防止客户端类调用它 - 只有子类可以调用或覆盖clone,并且这样做是bad idea。