【问题标题】:Type inference more restrictive in JDK 7 than JDK 6?JDK 7 中的类型推断比 JDK 6 更严格?
【发布时间】:2011-12-28 19:26:40
【问题描述】:

我认为这可能与Why does a generic cast of a List<? extends Set..> to List<Set..> succeed on Sun JDK 6 but fail to compile on 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;
    }
}

但是,在 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 下有效的类型。

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

【问题讨论】:

  • Java 8 (1.8.0_25) 再次编译就好了。

标签: java generics type-inference java-7


【解决方案1】:

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

这可以被视为规范的失败。这就是规范推断R 的方式:首先有约束R :&gt; BigDecimal,其中:&gt; 表示是 的超类型。然后推理规则选择R=BigDecimal,因为它是满足约束的最具体的类型。

现在,由于T:&gt;R、T:&gt;BigDecimal,人们会认为这也应该产生T=BigDecimal。

不幸的是,推理规则没有考虑T:&gt;R。 T 没有限制。 T不是通过同样的原理推断出来的。

虽然很烂,但规范就是规范。您的代码不应编译。 Javac6 那里出错了。

在 Java 8 中,推理规则有了很大改进,使 lambda 表达式更易于使用。希望您的代码应该在 Java 8 中编译。

【讨论】:

猜你喜欢
  • 2011-10-05
  • 1970-01-01
  • 1970-01-01
  • 2017-06-04
  • 1970-01-01
  • 2021-09-21
  • 2014-04-15
  • 2014-02-02
  • 1970-01-01
相关资源
最近更新 更多