java - 编译器对泛型方法的空参数的行为不同

标签 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);
      }
}

我简化了代码,所以现在根本不用 T。不过,我看不出错误的原因。 出于某种原因,javac 决定 T 代表 Object,然后提示 Object 不符合 T 的边界(这是真的):

HowBizarre.java:6: incompatible types; inferred type argument(s) java.lang.Number,java.lang.Object do not conform to bounds of type variable (s) P,T

found : <P,T>void

required: void

       doIt(null);
           ^

请注意,如果我将 null 参数替换为非 null 值,它可以正常编译。

哪个编译器的行为正确,为什么?这是其中之一的错误吗?

最佳答案

问题是由于 JLS 规范规定,否则无法推断的类型参数必须推断为 Object ,即使它不满足边界(并因此触发编译错误)。

以下是“错误”报告的摘录(为清楚起见,对其进行了进一步注释):

"Bug" ID 6299211 - method type variable: inference broken for null

This program does not compile:

public class Try {
    void m() {
        java.util.Collections.max(null);
    }
}

State: CLOSED, NOT A DEFECT.

Evaluation: THIS IS NOT A BUG. The inference algorithm cannot gather any information from the argument (null) and the method is not called in a place where there are any expectations on the returned value. In such cases the compiler must infer java.lang.Object for the type variable.


JLS 15.12.2.8 Inferring Unresolved Type Arguments

Any remaining type variables that have not yet been inferred are then inferred to have type Object


However, Object is not a subtype of Comparable<? super Object> and thus not within the bounds of the type variable in the declaration of Collections.max:

<T extendsObject & Comparable<? super T>> T max(Collection<? extends T>)


进一步探索

使用显式类型参数“修复”了这个问题:

HowBizarre.<Number,Integer>doIt(null); // compiles fine in javac

表明这与 null 关系不大参数和更多与类型推断信息的绝对缺乏有关,您可以尝试例如以下任一声明:

<T,U extends Comparable<T>> void doIt()

<T extends Number,U extends T> void doIt()

无论哪种情况,调用 doIt();不在 javac 中编译,因为它必须推断出 U成为Object根据 15.12.2.8,即使这样做会触发编译错误。


Eclipse 注释

虽然上面的代码片段都无法在某些版本的 javac 中编译,它们都在某些版本的 Eclipse 中执行。这表明 Eclipse 部分存在错误。众所周知,不同的编译器之间存在分歧。

相关问题

关于java - 编译器对泛型方法的空参数的行为不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3000177/

相关文章:

java - 使用 JSON Pretty Print 的优缺点?

java - @CucumberOptions 在 Cucumber-junit-platform-engine 中

java - 远程访问OrientDB嵌入式服务器

java - 比较映射忽略给定字段

java - 使用不包含类文件的java库

ios - Swift 泛型类型

Eclipse 无法在 Ubuntu 中启动

java - 如何使用批处理文件无限循环需要参数的 jar 文件?

java - 是否可以编写允许类型的子类型和类型本身的 Java 泛型表达式?

Java泛型列表中,如何处理List<MyClass<?>>