2015-09-03 16 views
5

Rozważmy następujący program:Dlaczego ten program kompiluje się z Java 7, ale nie z Java 8?

public class xx<T> { 

    <T> Iterable<T> createIterable(Class<T> cls) { 
     return null; 
    } 

    Iterable<? extends Number> createNumberIterable(boolean floatingPoint) { 
     return this.createIterable(floatingPoint ? Integer.class : Float.class); 
    } 
} 

Pod Java 7 kompiluje:

$ java -version 
java version "1.7.0_45" 
Java(TM) SE Runtime Environment (build 1.7.0_45-b18) 
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode) 
$ javac xx.java 
$ 

Pod Java 8 nie robi:

$ java -version 
java version "1.8.0_40" 
Java(TM) SE Runtime Environment (build 1.8.0_40-b25) 
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode) 
$ javac xx.java 
xx.java:8: error: method createIterable in class xx<T#2> cannot be applied to given types; 
     return this.createIterable(floatingPoint ? Integer.class : Float.class); 
       ^
    required: Class<T#1> 
    found: floatingPo[...]class 
    reason: inferred type does not conform to equality constraint(s) 
    inferred: Float 
    equality constraints(s): Float,Integer 
    where T#1,T#2 are type-variables: 
    T#1 extends Object declared in method <T#1>createIterable(Class<T#1>) 
    T#2 extends Object declared in class xx 
1 error 
$ 

A co jest prawdą:

  1. To jest błąd w Javie 7, który został naprawiony w Javie 8 (kompilator był zbyt permisywny); lub
  2. jest to nowy błąd, który został wprowadzony w Javie 8

Jeśli odpowiedź jest nr 1, można wyjaśnić w normalnym języku powód, dla którego JLS to nie pozwala, przy użyciu oczywistą interpretację?

(Uwaga: proszę nie wyjaśniają, jak obejść ten problem, że nie jest to kwestia)

+3

Wygląda na to, że odpowiedź znajduje się tutaj: http://stackoverflow.com/a/23880278/1172714 – dsh

+0

Spróbuj obejść - 'createIterable (klasa )' – ZhongYu

Odpowiedz

0

Ani był stary zachowanie to błąd, nie jest nowy zachowanie bug. Reguły dotyczące typu wyrażenia warunkowego stały się bardziej złożone, co w wielu przypadkach pomaga i nie zaszkodzi w twoim przypadku.

Kompilator nie pozwala na to, ponieważ typy Integer.class i Float.classnieporównywalny. Nie ma typu T, który spowodowałby, że Class<T> byłby nadtypem zarówno Class<Integer> jak i Class<Float>.

Powiązane problemy