Вывод типа более строгий в JDK 7, чем в JDK 6? - PullRequest
8 голосов
/ 28 декабря 2011

Я думаю, это может быть связано с Почему общий состав спискак спискупреуспеть в 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;
    }
}

Однако в JDK7, я получаю следующую ошибку:

[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. Однако здесь компилятор отклоняет тип, допустимый в JDK6.

Это ошибка?Или правила вывода стали более строгими для методов?

1 Ответ

3 голосов
/ 29 декабря 2011

Строго в соответствии со спецификацией, T не может быть выведен (согласно 15.12.2.7), поэтому его следует принять как Object.

Это можно рассматривать как сбой спецификации.Вот как спецификация выводит R: сначала есть ограничение R :> BigDecimal, где :> означает, что является супертипом .Затем в правилах вывода выбирается R=BigDecimal, поскольку это наиболее конкретный тип, удовлетворяющий ограничению.

Теперь, начиная с T:>R, T:>BigDecimal, можно подумать, что это также должно дать T=BigDecimal.

К сожалению, правила вывода не учитывают T:>R.На T нет никаких ограничений.T не выводится по тому же принципу.

Пока это отстой, спец.Ваш код не должен компилироваться.В Javac6 все не так.

В Java 8 значительно улучшены правила вывода, которые упрощают использование лямбда-выражений.Надеюсь, ваш код должен скомпилироваться в Java 8.

...