Why is this program compiling with Java 7, but not with Java 8?

Consider this program:

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); } } 

In Java 7, it compiles:

 $ 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 $ 

In Java 8, this is not:

 $ 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 $ 

And what is true:

  • This is a bug in Java 7 that is fixed in Java 8 (the compiler was too permissive); or
  • This is a new bug that was introduced in Java 8.

If the answer is No. 1, can you explain in plain language why JLS does not allow this using an obvious interpretation?

(Note: please do not explain how to solve the problem, this is not a question)

+5
source share
1 answer

The old behavior was not a mistake, and the new behavior was not a mistake. The rules for the type of conditional expression just got complicated, which helps in many cases and doesn’t really hurt in yours.

The compiler does not allow this because the types Integer.class and Float.class comparable. There is no type T that would make Class<T> supertype of both Class<Integer> and Class<Float> .

0
source

All Articles