JDK 7 中的类型推断比 JDK 6 中的限制更多?

发布于 2024-12-23 03:39:47 字数 1131 浏览 0 评论 0原文

我认为这可能与 为什么列表的泛型转换<?扩展集..>到列表<设置..>在 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;
    }
}

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

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

I think this might be related to 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?

If we take the following classes, they compile fine under 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;
    }
}

However, under JDK 7, I receive the following error:

[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;

I thought type inference was less restrictive (e.g., adding constructor inference) in JDK 7. However, here, the compiler is rejecting a type that is valid under JDK 6.

Is this a bug? Or were the rules on inference made more stringent for methods?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

人│生佛魔见 2024-12-30 03:39:47

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

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

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

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

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

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

Strictly according to the spec, T cannot be inferred (per 15.12.2.7), so it should be taken as Object.

This can be viewed as a failure of the spec. This is how spec infers R: first there is constraint R :> BigDecimal, where :> means is a supertype of. The inference rules then choose R=BigDecimal since it's the most specific type satisfying the constraint.

Now, since T:>R, T:>BigDecimal, one would think this should yield T=BigDecimal too.

Unfortunately the inference rules do not take T:>R into account. There is no contraint on T. T is not inferred through the same principle.

While it sucks, spec is spec. Your code should not compile. Javac6 is wrong there.

In Java 8 there's an great improvement on inference rules to make lambda expression easier to use. Hopefully your code should compile in Java 8.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文