如果我们采用以下类,它们可以在 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;
}
}
但是,在 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;
我认为类型推断在 JDK 7 中的限制较少(例如,添加构造函数推断)。但是,在这里,编译器拒绝在 JDK 6 下有效的类型。
这是一个错误吗?还是推理规则对方法更加严格?
最佳答案
严格按照规范,T
无法推断(根据 15.12.2.7),因此应将其视为 Object
.
这可以被视为规范的失败。这就是 spec 推断 R
的方式: 首先有约束 R :> BigDecimal
, 其中:>
表示 是 的父类(super class)型。然后推理规则选择R=BigDecimal
因为它是满足约束的最具体的类型。
现在,自 T:>R
, T:>BigDecimal
, 人们会认为这应该产生 T=BigDecimal
也是。
不幸的是推理规则不采用T:>R
考虑到。 T
没有约束. T
不是通过相同的原理推断的。
虽然很烂,但规范就是规范。您的代码不应编译。 Javac6 那里是错误的。
在 Java 8 中,推理规则有了很大的改进,使 lambda 表达式更易于使用。希望您的代码可以在 Java 8 中编译。
关于java - JDK 7 中的类型推断比 JDK 6 更严格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8660316/