当我们说基类Base
及其派生类Derived
为type compatible
时,我们指的是Base
引用可以引用{{1}实例。
即Derived
对于oposite,需要一个铸件,因为类型不是类型兼容的
现在这个概念不适用于原始类型吗?
我是说这个
Base b = new Derived();
对我来说似乎是一样的(因为也不需要强制转换,short shortNumber = 10;
int intNumber = shortNumber;
和short
都是整数类型。)
因此,当重写基类中的方法时,为什么可以接受返回类型与基类返回类型相同或至少类型兼容,但这不适用于整数类型,例如?
例如。为什么这是不可接受的?
int
答案 0 :(得分:7)
直接答案,为什么您的代码示例无效,很简单:协变返回类型的Java语言功能明确地将不应用于原语< / strong>即可。请参阅JLS 8.4.5和JLS 8.4.8.3。
Autoboxing不适用于此处。如果您将返回类型更改为Integer
和Short
,则它们仍然不是返回类型可替换的,因为它们都不是另一个的子类。
我无法回答“为什么JLS不允许原语的协变返回类型”这一问题,即为什么语言设计者认为不应该允许它。
答案 1 :(得分:3)
从Java 1.5开始,您的short和int都可以自动插入Short
和Integer
,而Short不会扩展Integer(例如,它有不同的MAX_VALUE)。
这是造成问题的原因之一,但我认为真正的原因是java语言设计决策之一:如果您要更改类型,我们希望您了解它。
答案 2 :(得分:2)
你不能在返回类型的基础上覆盖方法,它是不允许的,编译器会抱怨它不会被视为重写方法。
此外,函数调用在返回类型的基础上不是确定性的。例如,如果你打电话
someObj.getId();
编译器如何确定应该调用哪个方法?从编译器的角度来看,你没有处理返回的值无关紧要。
答案 3 :(得分:2)
JLS #8.4.8.3:覆盖和隐藏的要求
如果返回类型为R1的方法声明d1覆盖或隐藏了另一个返回类型为R2的方法d2的声明,那么对于d2,d1必须是return-type-substitutable(第8.4.5节),或者是编译时错误发生。
此规则允许协变返回类型 - 在覆盖方法时优化方法的返回类型。
JLS #8.4.5:方法返回类型 - 对象和原始元素的处理方式不同(强调我的):
带有返回类型R1的方法声明d1是返回类型 - 可替代另一个返回类型为R2的方法d2,当且仅当以下条件成立时:
- 如果R1无效,则R2无效。
- 如果R1是基本类型,则R2与R1相同。
- 如果R1是参考类型,那么:
- R1可以是R2的子类型,也可以通过未经检查的转换(第5.1.9节)将R1转换为R2 的子类型,或
- R1 = | R2 |
至于您的初始示例,它被称为扩展转换(short - &gt; int),并且不适用于方法重写的上下文。