为什么类型兼容性在覆盖方法时也不适用于原语?

时间:2012-07-22 09:11:34

标签: java inheritance polymorphism override

当我们说基类Base及其派生类Derivedtype compatible时,我们指的是Base引用可以引用{{1}实例。
Derived
对于oposite,需要一个铸件,因为类型不是类型兼容的 现在这个概念不适用于原始类型吗? 我是说这个

Base b = new Derived();

对我来说似乎是一样的(因为也不需要强制转换,short shortNumber = 10; int intNumber = shortNumber; short 都是整数类型。) 因此,当重写基类中的方法时,为什么可以接受返回类型与基类返回类型相同或至少类型兼容,但这不适用于整数类型,例如? 例如。为什么这是不可接受的?

int

4 个答案:

答案 0 :(得分:7)

直接答案,为什么您的代码示例无效,很简单:协变返回类型的Java语言功能明确地将应用于原语< / strong>即可。请参阅JLS 8.4.5JLS 8.4.8.3

Autoboxing不适用于此处。如果您将返回类型更改为IntegerShort,则它们仍然不是返回类型可替换的,因为它们都不是另一个的子类。

我无法回答“为什么JLS不允许原语的协变返回类型”这一问题,即为什么语言设计者认为不应该允许它。

答案 1 :(得分:3)

从Java 1.5开始,您的short和int都可以自动插入ShortInteger,而Short不会扩展Integer(例如,它有不同的MAX_VALUE)。

这是造成问题的原因之一,但我认为真正的原因是java语言设计决策之一:如果您要更改类型,我们希望您了解它。

答案 2 :(得分:2)

你不能在返回类型的基础上覆盖方法,它是不允许的,编译器会抱怨它不会被视为重写方法。

此外,函数调用在返回类型的基础上不是确定性的。例如,如果你打电话

someObj.getId();

编译器如何确定应该调用哪个方法?从编译器的角度来看,你没有处理返回的值无关紧要。

答案 3 :(得分:2)

  1. JLS #8.4.8.3:覆盖和隐藏的要求

      

    如果返回类型为R1的方法声明d1覆盖或隐藏了另一个返回类型为R2的方法d2的声明,那么对于d2,d1必须是return-type-substitutable(第8.4.5节),或者是编译时错误发生。
      此规则允许协变返回类型 - 在覆盖方法时优化方法的返回类型。

  2. JLS #8.4.5:方法返回类型 - 对象和原始元素的处理方式不同(强调我的):

      

    带有返回类型R1的方法声明d1是返回类型 - 可替代另一个返回类型为R2的方法d2,当且仅当以下条件成立时:

         
        
    • 如果R1无效,则R2无效。
    •   
    • 如果R1是基本类型,则R2与R1相同。
    •   
    • 如果R1是参考类型,那么:   
          
      • R1可以是R2的子类型,也可以通过未经检查的转换(第5.1.9节)将R1转换为R2 的子类型,或
      •   
      • R1 = | R2 |
      •   
    •   
  3. 至于您的初始示例,它被称为扩展转换(short - &gt; int),并且不适用于方法重写的上下文。