java - JDK 7 中的类型推断比 JDK 6 更严格?

标签 java generics type-inference java-7

我认为这可能与 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 下有效的类型。

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

最佳答案

严格按照规范,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/

相关文章:

java - 通过隐藏 Manifest 并将代码转换为 Unicode 字符来保护应用程序不被反编译

java 参数化泛型静态工厂

haskell - 你能在 Haskell 中部分约束一个类型吗?

swift - print() 的长参数产生错误 "Expression was too complex to be solved"

java - 为什么这个与 lambda 相关的类型推断会失败?

java - 在android中更快地下载给定url的图像

java - 如何使用第一个 JSON 对象覆盖第二个 JSON 对象

java - 调试 Java JVM 崩溃 - native 代码访问

java - < 和 > 是什么意思,比如 implements Comparable<BigInteger>?

java - 泛型和继承 - 代码中只需要父类(super class)型