Eya*_*der 16 java eclipse generics null compilation
以下代码与Eclipse完美编译,但无法使用javac进行编译:
public class HowBizarre {
public static <P extends Number, T extends P> void doIt(P value) {
}
public static void main(String[] args) {
doIt(null);
}
}
Run Code Online (Sandbox Code Playgroud)
我简化了代码,所以现在根本不使用T. 不过,我没有看到错误的原因.由于某种原因,javac决定T代表Object,然后抱怨Object不符合T的界限(这是真的):
HowBizarre.java:6:不兼容的类型; 推断类型参数java.lang.Number,java.lang.Object不符合类型变量的范围P(T)
发现:
<P,T>无效要求:无效
Run Code Online (Sandbox Code Playgroud)doIt(null); ^
请注意,如果我将null参数替换为非null值,则编译正常.
哪个编译器行为正确,为什么?这是其中之一的错误吗?
pol*_*nts 18
问题是由于JLS规范要求必须推断出不可推断的类型参数Object,即使它不满足边界(并因此会触发编译错误).
以下是"错误"报告的摘录(为了清楚起见,已进一步注释):
"Bug"ID 6299211 - 方法类型变量:推断为null
这个程序不编译:
Run Code Online (Sandbox Code Playgroud)public class Try { void m() { java.util.Collections.max(null); } }州:关闭,而不是缺陷.
评价:这不是一个BUG.推理算法不能从argument(
null)中收集任何信息,并且在对返回值有任何期望的地方不调用该方法.在这种情况下,编译器必须推断出java.lang.Object类型变量.
然后推断任何尚未推断的剩余类型变量具有类型
Object
但是,
Object它不是子类型,Comparable<? super Object>因此不在声明中的类型变量的范围内Collections.max:
<T extendsObject & Comparable<? super T>> T max(Collection<? extends T>)
使用显式类型参数"修复"问题:
HowBizarre.<Number,Integer>doIt(null); // compiles fine in javac
Run Code Online (Sandbox Code Playgroud)
为了表明这与null参数关系较少,而更多地与类型推理的绝对缺乏信息有关,您可以尝试以下任一声明:
<T,U extends Comparable<T>> void doIt()
<T extends Number,U extends T> void doIt()
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,调用doIt();不编译javac,因为它必须推断U是Object按照15.12.2.8,即使这样做会引发编译错误.
虽然上面的代码片段都没有在某个版本中编译javac,但它们都在某个版本的Eclipse中完成.这将暗示Eclipse的一个错误.众所周知,不同的编译器之间存在分歧.
| 归档时间: |
|
| 查看次数: |
3622 次 |
| 最近记录: |