返回类型歧义

时间:2011-08-28 17:14:34

标签: java return-type cloneable

请考虑以下Java编程语言书中的代码

public class MyClass extends HerClass implements Cloneable {
   public MyClass clone()
       throws CloneNotSupportedException {
       return (MyClass) super.clone();
   }
   // ...
}

当覆盖clone()函数已经将返回类型设置为MyClass时,那么在return语句中再次指定它的要求是什么? 此外,由于正在创建Myclass的超类对象的克隆(因为clone()被称为wrt超类),它怎么可能是Myclass类型?

提前致谢

4 个答案:

答案 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()访问权限,但由于您是从子类调用它,因此它不是问题。

相关问题