请考虑以下Java编程语言书中的代码
public class MyClass extends HerClass implements Cloneable {
public MyClass clone()
throws CloneNotSupportedException {
return (MyClass) super.clone();
}
// ...
}
当覆盖clone()函数已经将返回类型设置为MyClass时,那么在return语句中再次指定它的要求是什么? 此外,由于正在创建Myclass的超类对象的克隆(因为clone()被称为wrt超类),它怎么可能是Myclass类型?
提前致谢
答案 0 :(得分:1)
因为clone()
返回Object类的对象,所以必须将其强制转换为正确的类型。但是你知道它是MyClass类型的对象,所以强制转换是正确的。
答案 1 :(得分:1)
理论上你是对的:因为你必须指定函数返回值的类型,编译器可以尝试自动执行更正。另一方面,需要显式转换有助于识别可能的错误。
除非您有特定要求,clone()
类的Object
方法已经做了正确的事情,即它创建了正确类的对象并复制了克隆对象中的所有非静态属性。但是它不能将它作为派生类型返回,因为在编译时Object
类本身不知道该类型。
确实可以为所有类自动提供clone()
方法,但有时您不希望它可用,有时您想要覆盖默认行为;例如,您的类中可能有一个id
属性,即使在克隆时,您希望每个类的实例都有不同的属性。必须覆盖clone()
方法,才能为您提供实现此类功能的位置。
答案 2 :(得分:1)
这是因为Object中的clone()
方法返回Object
。但是,您可以在clone()中返回子类,因为它扩展了Object。如果MyClass
中的方法看起来像这样
public Object clone()
然后它仍然是一个有效的可克隆对象,它会工作。你不需要施放任何东西。接口Cloneable
只是一个标记接口,这意味着它实际上没有任何方法。
答案 3 :(得分:1)
首先是您的简单问题:为什么super.clone()
会被转移到MyClass
?这是因为HerClass.clone()
的声明指定了HerClass
的返回值,因此您必须将其强制转换为正确的类型。
现在,对于更难的问题:super.clone()
如何实际返回MyClass
的实例?我实际上很难找到答案,但我确实在Joshua Bloch的Effective Java中找到了答案。 <{1}}的背景中仍有一些“神奇”,我不太明白。
书中的第11项:
在实践中,程序员假设他们扩展一个类并调用它 来自子类的super.clone,返回的对象将是一个实例 的子类。超类可以提供此功能的唯一方法 功能是返回通过调用super.clone获得的对象。 如果clone方法返回由构造函数创建的对象,它将会 有错误的课程。因此,如果您覆盖了一个克隆方法,那么 非最终类,你应该返回一个通过调用获得的对象 super.clone 即可。如果所有类的超类都遵守这个规则,那么 调用super.clone最终会调用Object的clone方法, 创建一个合适的类的实例。
我最初尝试通过编写程序来回答您的问题而不必总是致电Object.clone()
。我super.clone()
的自制克隆方法返回了从构造函数(HerClass
)生成的HerClass
的新实例。代码已编译,但在我尝试转换new HerClass()
时执行失败。只有从(MyClass) super.clone()
链接的方法才能返回一个值,该值是其子类型之一的实例。
请注意,如果未明确实现Object.clone()
,则默认情况下只返回HerClass.clone()
。默认方法具有Object.clone()
访问权限,但由于您是从子类调用它,因此它不是问题。