协变返回类型是否覆盖jls?

时间:2014-05-12 20:31:28

标签: java compilation override

简单地说,我的问题的关键是学会理解jls。我相信所有jls都是真的。

考虑jls的下一个片段:

  

8.4.8.1。覆盖(通过实例方法)

     

在类C中声明的实例方法m1会覆盖另一个实例   方法m2,在A类中声明如果满足以下所有条件:

     

C是A的子类。

     

m1的签名是m2签名的子签名(§8.4.2)。

     

或者:

     

m2是公共,受保护或声明的默认访问权限   打包为C,或

     

m1覆盖方法m3(m3与m1不同,m3与m2不同),   这样m3就会覆盖m2。

     

此外,如果m1不是抽象的,则说m1实现任何和   它覆盖的所有抽象方法声明。

转到子签名声明:

  

方法m1的签名是a的签名的子签名   方法m2如果:

     

m2与m1具有相同的签名,或

     

m1的签名与签名的擦除(§4.6)相同   m2。

关于同一签名:

  

如果两个方法具有相同的名称,则它们具有相同的签名   参数类型。

哪个规则允许使用协变返回类型?

1 个答案:

答案 0 :(得分:4)

这些规则都不允许协变返回类型。方法的签名是指方法名称及其参数的类型和顺序,而不是返回类型。

From JLS, Section 8.4.8.3

  

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

     

此规则允许协变返回类型 - 在覆盖方法时优化方法的返回类型。

Section 8.4.5,其中指出:

  

返回类型为R1的方法声明d1是另一个方法d2的return-type-substitutable,返回类型为R2 iff以下任何一个为真:

     
      
  • 如果R1无效,则R2无效。

  •   
  • 如果R1是基本类型,则R2与R1相同。

  •   
  • 如果R1是引用类型,则以下之一为真:

         
        
    • R1,适应d2(§8.4.4)的类型参数,是R2的子类型

    •   
    • 可以通过未经检查的转换(第5.1.9节)将R1转换为R2的子类型。

    •   
    • d1与d2(§8.4.2)的签名不同,R1 = | R2 |。

    •   
  •   

(强调我的)

我加粗的部分允许协变返回类型。