generics - Oracle JDK 和 Eclipse JDT 编译器不同意!哪个编译不正确?不寻常的泛型和推理

标签 generics java eclipse-jdt compiler-bug

我有一段代码在 Oracle JDK 7 和 Eclipse JDT 7 之间编译不一致,但由于我不确定哪个编译器出错,我想我应该在提交任何代码之前在这里征求意见错误报告。

这是我能想出的最简单的测试来证明不一致:

interface Foo<S extends Foo<S, T>, T> {
    // should this compile?
    public <X extends Foo<S, Y>, Y> Y method1();

    // what about this?
    public <X extends Foo<? extends S, Y>, Y> Y method2();
}

Oracle JDK 在 method1 上给出了一个错误,但在 method2 上没有,而 Eclipse 对这两个方法都没有问题。我什至不确定任一个方法是否应该编译...

如果这两个方法都不应该编译开始,那么下面的观点就没有实际意义了,但我觉得如果我们添加以下代码,两个编译器都会犯错误:

interface Bar extends Foo<Bar, Integer> {
}

class Bug {
    void bug() {
        Bar bar = null;
        Double bubble;

        // these fail as expected...
        bar.<Foo<Bar, Double>, Double> method1();
        bar.<Foo<? extends Bar, Double>, Double> method2();

        // ...but these don't even though the inferred parametrisations should be
        // the same as above
        Double bobble = bar.method1();
        Double babble = bar.method2();
    }
}

当我们为 method1 和 method2 提供显式参数化时,我找不到任何会导致返回 Double 的有效调用的方法(即,当 Y 用 Double 参数化时,我找不到 X 的有效参数化)。这是我期望的行为,据我所知,这里的 Y 应该只能用 Integer 进行参数化。

但是,当我们让编译器推断参数化时,Oracle JDK 和 Eclipse JDT 都允许将 Y 推断为 Double 的调用。如果您将鼠标悬停在 Eclipse 中的调用上,它甚至会显示参数化与我们的手动调用完全相同,但失败了,那么为什么会有不同的行为呢?

(此时分配给新变量 bobble 和 babble 的原因是悬停文本显示不同的参数化——出于某种原因将 Double 替换为 Object——如果我们再次分配给 bubble。它仍然编译两个调用并分配给虽然是 double ,所以我不知道这是为什么。)

所以,这可能是我提出的另一个相当模糊的问题,但是这里的任何人都可以为我阐明这个问题吗?

编辑:

Eclipse 错误报告:https://bugs.eclipse.org/bugs/show_bug.cgi?id=398011

最佳答案

编译器似乎做了某种简化。 Foo.method1Foo.method2用两个参数声明,XY ,其中之一可以在推理过程中确定,但是 X根本没有使用。

所以当你调用Double bobble = bar.method1() X应计算为 extends Foo<Bar, Double> , 但编译器决定删除此参数,因为它未被使用。

当您显式指定方法参数时,编译器必须检查它们的正确性并按预期失败。

如果您更改这些方法中的任何一个以接受类型为 X 的参数那么您就不会遇到这种模棱两可的情况,因为您将为编译器提供一些信息,这些信息将用于确定实际 X .

Eclipse 在其编译器完全没有显示错误时有几个这样的错误,但是 javac开始提示不正确的方法调用。避免此类错误的最佳方法是使用显式参数,在这种情况下,大多数编译器的行为几乎相同。因此,如果您对显式参数有疑问,最好重新设计您的类。

关于generics - Oracle JDK 和 Eclipse JDT 编译器不同意!哪个编译不正确?不寻常的泛型和推理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13980552/

相关文章:

java - Eclipse JDT 编译器 (ECJ) 在 Java 1.7 中抛出 NPE

delphi - 在另一个泛型类声明的约束中使用泛型接口(interface)

Java:如何在运行时获取泛型类型?

Java 日期偏移格式问题?

java - str1 != "NO"当 str1 为 "NO"时返回 true

c# - C# 或其他语言中的 Scala 风格抽象模块?

java - Eclipse 中的方法重构

c# - 寻找我当前方法调用的 C# 泛型版本

java - 如何将整数数组传递给需要 `Array<T>` 的方法?

java - 识别 IType 的所有 IMethods 的访问器和修改器(getters/setters)