2011-12-28 13 views
8

myślę, że to może być związane z 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?Czy wnioskodawca jest bardziej restrykcyjny w JDK 7 niż JDK 6?

Jeśli weźmiemy następujące klasy, one skompilować grzywny pod 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; 
    } 
} 

Jednak pod JDK 7, pojawia się następujący błąd:

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

Myślałem, że wnioskowanie o typie było mniej restrykcyjne (np. Dodawanie wnioskowania konstruktora) w JDK 7. Jednak tutaj kompilator odrzuca typ, który jest ważny w JDK 6.

Czy to błąd? A może zasady dotyczące wnioskowania stały się bardziej rygorystyczne w odniesieniu do metod?

+0

Java 8 (1.8.0_25) to kompilacja znowu dobrze. – Lii

Odpowiedz

3

Ściśle zgodnie ze specyfikacją, T nie można wywnioskować (na 15.12.2.7), dlatego należy go traktować jako Object.

Można to uznać za błąd specyfikacji. W ten sposób podaje się specyfikację R: po pierwsze istnieje ograniczenie R :> BigDecimal, gdzie :> oznacza jest nadtypem. Reguły wnioskowania następnie wybierają R=BigDecimal, ponieważ jest to najbardziej specyficzny typ spełniający ograniczenie.

Teraz, od T:>R, T:>BigDecimal, można by pomyśleć, że powinno to również dać T=BigDecimal.

Niestety reguły wnioskowania nie biorą pod uwagę T:>R. Nie ma żadnych ograniczeń dotyczących T. T nie wywnioskowano na tej samej zasadzie.

Podczas gdy jest do bani, specyfikacja jest spec. Twój kod nie powinien się kompilować. Javac6 jest tam nie tak.

W języku Java 8 wprowadzono znaczną poprawę reguł wnioskowania, aby ułatwić korzystanie z wyrażenia lambda. Mam nadzieję, że Twój kod powinien się skompilować w języku Java 8.

+0

Dziękuję za wyjaśnienie. Ulżyło mi, że wnioskowanie o typie jest poprawne w JDK 7 (nieco przygnębione, ale działało ono przypadkowo w JDK 6). Wydaje się, że jest to związane z: http://www.oracle.com/technetwork/java/javase/compatibility-417013.html. (Przywoływany pierwotnie na http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6638712). – Saish

Powiązane problemy