如何解决Java 8 中的编译器错误,Java 6 中没有错误,为什么?
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
class B { }
class C extends B { }
class D { }
class Test {
void test() {
List<B> lb = new ArrayList<B>();
List<C> lc = new ArrayList<C>();
Iterable<B> it = lb == null ? lc : lb; // a
FluentIterable.from(lb == null ? lc : lb).transform(new Function<B,D>() { // b
@Override
public D apply(B b) {
return null;
}
});
}
}
在 Java 8 行 //b 下给我这些编译器错误:
Incompatible types. Found: 'java.util.List<C>',required: 'java.util.List<capture<? extends B>>'
Incompatible types. Found: 'java.util.List<B>',required: 'java.util.List<capture<? extends B>>'
在 Java 6 下,同一行编译得很好。
行//a
Iterable<B> it = lb == null ? lc : lb;
产生编译错误
Incompatible types. Found: 'java.util.List<C>',required: 'java.lang.Iterable<B>'
在 Java 6 和 Java 8 下都是正确的。
但是 Guava 的 FluentIterable.from 只是对 Iterable 的封装。为什么它在 Java 6 下不会产生任何错误而在 Java 8 下会产生错误?它与我在 //a 行的内容有何不同?
谢谢。
解决方法
TL;DR 在 Java 8 中更改了类型推断的语言规范。
行 //a 是编译时错误,因为 List
List<C> listOfC = new ArrayList<C>();
Iterable<B> listOfB = listOfC; // if this were allowed it would be bad
listOfB.add(new B()); // ...because now my list of C's has a B in it
C reallyAB = listOfC.get(0); // ...and now i have an object of type B in a variable of type C
reallyAB.methodThatsDefinedOnAC(); // ...and crash
对于编译器来说,检测不合理的赋值很简单,因为 //a 行上的变量具有显式类型。
行 //b 更复杂,因为该方法具有泛型类型参数,因此编译器必须在检查参数的同时推断方法的类型。随着 Java 8 的发布,关于如何推断类型参数的规则发生了显着变化,Java 8 将 Lambda 引入到语言中,旨在改进大多数情况下的类型推断。
https://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html
此处提供了有关为什么三元运算符现在无法满足泛型类型约束的详细分析:Generics compilation error with ternary operator in Java 8,but not in Java 7
规范之间的不兼容记录在这个jdk bug中:https://bugs.openjdk.java.net/browse/JDK-8044053
您可以通过提供显式类型来克服规则中的限制。您可以将表达式结果分配给一个变量并将该变量传递给调用,或者您可以强制转换表达式。
void test() {
List<B> lb = new ArrayList<B>();
List<C> lc = new ArrayList<C>();
FluentIterable.from((List<? extends B>)(lb == null ? lc : lb)).transform(new Function<B,D>() { // b
@Override
public D apply(B b) {
return null;
}
});
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。