2011-12-28 4 views
8

Я думаю, что это может быть связано с 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 7, чем JDK 6?

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

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

+0

Java 8 (1.8.0_25) снова скомпилируется. – Lii

ответ

3

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

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

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

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

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

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

+0

Благодарим вас за объяснение. Я с облегчением понял, что вывод типа верен в JDK 7 (он несколько обескуражил его, что он случайно работал в JDK 6). Кажется, это связано с: http://www.oracle.com/technetwork/java/javase/compatibility-417013.html. (Исправлено по адресу http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6638712). – Saish

Смежные вопросы