为什么这个程序可以用 Java 7 而不是 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);
}
}
在 Java 7 下编译:
Under 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
$
在 Java 8 下没有:
Under Java 8 it does 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
$
这是真的:
- 这是 Java 7 中的错误,在 Java 8 中得到修复(编译器过于宽容);或
- 这是 Java 8 中引入的一个新错误
如果答案是 #1,你能用普通语言解释为什么 JLS 不允许这样做,使用明显的解释吗?
If the answer is #1, can you explain in normal language the reason why the JLS doesn't allow this, using the obvious interpretation?
(注意:请不要解释如何解决问题,这不是问题)
(Note: please don't explain how to workaround the problem, that's not the question)
旧行为不是错误,新行为也不是错误.条件表达式类型的规则变得更加复杂,这在很多情况下都有帮助,而对您的情况并没有真正的伤害.
Neither was the old behavior a bug, nor is the new behavior a bug. The rules for the type of the conditional expression just got more complex, which helps in many cases and doesn't really hurt in yours.
编译器不允许,因为Integer.class
和Float.class
的类型不可比.没有类型 T
会使 Class
成为 Class
和 Class
The compiler does not allow it because the types of Integer.class
and Float.class
are incomparable. There is no type T
which would make Class<T>
a supertype of both Class<Integer>
and Class<Float>
.