Cod*_*ete 6 java generics inheritance
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;}
}
Run Code Online (Sandbox Code Playgroud)
为什么在Derived类中定义重写方法f1()和f3()不会产生编译错误,比如Derived类中的重写f2()方法的定义(它给出编译错误"返回类型与Base.f2()不兼容")?
JLS中的子签名覆盖规则允许覆盖方法(在Derived类中)是非泛型的,而重写方法(在Base类中)是通用的.
未经检查的覆盖规则允许在子类List<String>而不是List<T>在Base类中生成返回类型.
但我无法解释下面的行为差异,我不明白为什么fin()和f3()覆盖Derived类中的定义成功编译(在Eclipse,SE8上),忽略了f3()的有界类型参数所施加的限制f1()的有界通配符!
PS我的猜测 - 在衍生编译器中的f1()和f3()中将两个方法视为仅返回"原始"列表 - 编译器首先进行擦除(此时仅在Derived!中),然后在Derived中比较这些已擦除的方法Base中未删除(迄今为止)的方法.现在未经检查的覆盖规则是正常的(并且不需要检查边界 - 这根本不可能),编译器决定这是正确的覆盖和编译更进一步......在Base.f1()和Base的编译泛型结束时的某处.f3()也擦掉:)))
这个SO答案也为这个主题增加了想法.
尽管原始声明是通用的,但您的f1和覆盖不是通用的。f3编译允许覆盖的返回类型与原始返回类型不同,因为它们具有相同的类型擦除 ( List)。我认为这是JLS 8.4.5的结果,尽管坦率地说,我发现规范的这一部分有点令人困惑。
如果您将覆盖再次更改为通用:
<T> List<String> f1() {return null;}
<T extends Number> List<String> f3() {return null; }
Run Code Online (Sandbox Code Playgroud)
...然后都无法编译:
error: <T#1>f1() in Derived cannot override <T#2>f1() in Base
<T> List<String> f1() {return null;}
^
return type List<String> is not compatible with List<? extends Number>
where T#1,T#2 are type-variables:
T#1 extends Object declared in method <T#1>f1()
T#2 extends Object declared in method <T#2>f1()
error: <T#1>f3() in Derived cannot override <T#2>f3() in Base
<T extends Number> List<String> f3() {return null; }
^
return type List<String> is not compatible with List<T#1>
where T#1,T#2 are type-variables:
T#1 extends Number declared in method <T#1>f3()
T#2 extends Number declared in method <T#2>f3()
Run Code Online (Sandbox Code Playgroud)
请注意,即使在原始代码中,javac也会发出有关不安全转换的警告,并且如果您使用-Xlint:unchecked它,则会提供详细信息:
return type requires unchecked conversion from List<String> to List<? extends Number>
return type requires unchecked conversion from List<String> to List<T>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
210 次 |
| 最近记录: |