本文介绍了JDK 7中的类型推断在JDK 6中比JDK 6更具限制性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为这可能与



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

  public final class Foo< V> {

私人最终V值;

private Foo(final V value){

this.value = value;
}

public static< T,R extends T> FOO< T> (最终R值){

返回新的Foo< T>(值);



final class Tester {

@Test(groups =unit)

public static void test(){

bar(Foo.of(BigDecimal.ZERO)); //此行在JDK 7中失败,但不是JDK 6
}

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

assert target != null;


$ / code>

然而,在JDK 7下,我收到以下错误:

  [错误] \ work \fsb-core\src\test\java\com\ fsb\core\Foo.java:[42]错误:类Tester中的
方法栏不能应用于给定的类型;

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



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

严格按照规范 T 无法推断出来(每15.12.2.7),所以它应该被视为 Object 。



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

现在,既然 T:> R , T:> BigDecimal code>,人们会认为这应该会产生 T = BigDecimal 。



不考虑 T:> R 。对 T 没有任何限制。 T 不是通过同样的原理推断出来的。



尽管它很糟糕,spec是spec。你的代码不应该编译。 Javac6在那里是错误的。



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


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?

解决方案

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.

这篇关于JDK 7中的类型推断在JDK 6中比JDK 6更具限制性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 20:30