JDK 7中的类型推断比JDK 6更具限制性吗?

Sai*_*ish 8 java generics type-inference java-7

我认为这可能与为什么List的通用演员表有关?扩展Set ..>到List <Set ..>在Sun JDK 6上成功但在Oracle JDK 7上无法编译?

如果我们采用以下类,它们在JDK 6下编译正常:

public final class Foo<V> {

    private final V value;

    private Foo(final V value) {

        this.value = value;
    }

    public static <T, R extends T> Foo<T> of(final R value) {

        return new Foo<T>(value);
    }
}

final class Tester {

    @Test(groups="unit")

    public static void test() {

        bar(Foo.of(BigDecimal.ZERO));  // This line fails in JDK 7 but not JDK 6
    }

    private static void bar(final Foo<? extends Number> target) {

        assert target != null;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,在JDK 7下,我收到以下错误:

[ERROR] \work\fsb-core\src\test\java\com\fsb\core\Foo.java:[42,8] error:
              method bar in class Tester cannot be applied to given types;
Run Code Online (Sandbox Code Playgroud)

我认为类型推断在JDK 7中的限制性较小(例如,添加构造函数推断).但是,在这里,编译器拒绝在JDK 6下有效的类型.

这是一个错误吗?或者推理的规则是否对方法更加严格?

irr*_*ble 3

严格按照规范,T无法推断(根据 15.12.2.7),因此应将其视为Object

这可以被视为规范的失败。这就是spec 的推断方式R:首先存在constraint R :> BigDecimal,其中:>means是 的超类型。然后推理规则会进行选择,R=BigDecimal因为它是满足约束的最具体的类型。

现在,由于T:>RT:>BigDecimal,人们会认为这也应该产生T=BigDecimal

不幸的是,推理规则没有T:>R考虑在内。没有任何限制TT并不是通过同样的原理推断出来的。

虽然很糟糕,但规格就是规格。你的代码不应该编译。Javac6 那里是错误的。

Java 8 对推理规则进行了重大改进,使 lambda 表达式更易于使用。希望您的代码能够在 Java 8 中编译。