Java泛型和覆盖

Nat*_*ill 9 java generics

为什么会发生以下情况:

public class one{
   public <T extends Foo> Bar<Foo> function1() {}
   public Bar<Foo> function2(){}
}
Run Code Online (Sandbox Code Playgroud)
public class two<F extends Foo> extends one{
   public Bar<F> function1(){} //Doesn't throw an error
   public Bar<F> function2(){} //Throws an error
}
Run Code Online (Sandbox Code Playgroud)

通过说<T extends Foo>我说Foo可以用超类型覆盖?

注意:我的问题不是为什么function2()抛出错误...但为什么function1() 抛出错误.

Zho*_*gYu 6

这可能是编译器错误.

其原因Two.function1被认为是压倒一切的方法One.function1是从http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.2

签名与签名Two.function1的擦除相同One.function1.

这是为了允许遗留子类型(Two)在超类型(One)被生成后仍然编译.

之后,javac需要检查返回类型:

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.8.3

如果具有返回类型R1的方法声明d1覆盖或隐藏具有返回类型R2的另一个方法d2的声明,则对于d2,d1必须是return-type-substitutable(第8.4.5节),否则会发生编译时错误.

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.5

R1可以是R2的子类型,也可以通过未经检查的转换(第5.1.9节)将R1转换为R2的子类型,或者R1 = | R2 |

http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.9

从原始类或接口类型(第4.8节)G到表单G的任何参数化类型都有未经检查的转换.

未经检查的转换不适用于此处R1=Bar<F>, R2=Bar<Foo>.这就是为什么Javac报告function2返回类型存在冲突的原因.

Javac应报告相同的错误function1.我猜测在上一步中,javac删除了One.function1,这是Bar function1()错误地使用该版本进行检查Two.function1- R2=Bar因此,这R1是一个子类型($ 4.10.2)R2,因此返回类型是兼容的.(但是,如果该理论是正确的,那么就不应该有"未经检查"的警告)