为什么会发生以下情况:
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() 不抛出错误.
这可能是编译器错误.
其原因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,因此返回类型是兼容的.(但是,如果该理论是正确的,那么就不应该有"未经检查"的警告)