public class Base {
<T> List<? extends Number> f1() {return null;}
List<? extends Number> f2() {return null;}
<T extends Number> List<T> f3() {return null; }
}
class Derived extends Base {
List<String> f1() {return null;} // compiles fine !!!
List<String> f3() {return null; } // compiles fine !!!
// compile ERR: return type is incompatible with Base.f2()
List<String> f2() {return null;}
}
为什么覆盖方法F1()和派生类F3()的定义,得到没有编译错误,如在派生类(其给出编译错误“返回类型重写F2()方法的定义与基本不相容。 f2()“)?当使用非泛型方法重写泛型方法时,为什么副标记和未检查的规则在返回类型上以这种方式工作?
JLS中的子签名覆盖规则允许覆盖方法(在Derived类中)是非泛型的,而覆盖方法(在Base类中)是泛型的。
未经检查的覆盖规则允许在子类List<String>
中生成返回类型,而不是基类中的List<T>
。
但我无法解释下面的行为差异,我不明白为什么f1()和f3()覆盖Derived类中的定义已成功编译(在Eclipse,SE8上),忽略了有界类型参数f3()和有界通配符f1()!
P.S.我的猜测 - 在Derived编译器中的f1()和f3()中,将这两种方法视为仅返回“raw”。List - 编译器首先进行擦除(此时仅在Derived !?中),然后将Derived中的这些擦除方法与未擦除(到目前为止)在Base中的方法。现在未检查覆盖规则是可以的(并且不需要检查边界 - 它根本不可能),编译器决定这是正确的覆盖并且编译进一步...以及Base.f1()和Base中编译泛型末尾的某处.f3()也删除:)))
This SO answer也增加了这个主题的想法。