Java 8 Java 8中的编译器错误,Java 6中没有错误,为什么?

Java 8 Java 8中的编译器错误,Java 6中没有错误,为什么?,java-8,compiler-errors,guava,iterable,java-6,Java 8,Compiler Errors,Guava,Iterable,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> l

我有以下代码:

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;
            }
        });
    }
}
import java.util.ArrayList;
导入java.util.List;
导入com.google.common.base.Function;
导入com.google.common.collect.fluentiable;
B类{}
类C扩展了B{}
类D{}
课堂测试{
无效测试(){
List lb=new ArrayList();
List lc=new ArrayList();
Iterable it=lb==null?lc:lb;//a
FluentIterable.from(lb==null?lc:lb).transform(新函数(){//b
@凌驾
公开申请(B){
返回null;
}
});
}
}
在Java 8下,line//b给出了以下编译器错误:


不兼容的类型。找到:'java.util.List',必需:'java.util.ListTL;DR在Java 8中更改了类型推断的语言规范。

//a是一个编译时错误,因为列表不能分配给Iterable类型的变量。如果是,那么您可以编译以下不健全的代码

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
List listOfC=new ArrayList();
Iterable listOfB=listOfC;//如果这被允许,那将是糟糕的
添加(新的B());/。。。因为现在我的C名单上有一个B
C reallyAB=listOfC.get(0);/。。。现在我有一个类型为B的对象,在一个类型为C的变量中
reallyAB.MethodsDefinedOnAC();/。。。和崩溃
检测不合理的赋值对于编译器来说很简单,因为//a行上的变量具有显式类型

//b更复杂,因为该方法具有泛型类型参数,因此编译器必须在检查参数的同时推断方法的类型。随着Java8的发布,围绕如何推断类型参数的规则发生了显著的变化,Java8将Lambdas引入到语言中,目的是在大多数情况下改进类型推断

这里详细分析了三元运算符现在无法满足泛型类型约束的原因:

规范之间的不兼容性记录在此jdk错误中:

您可以通过提供显式类型来克服规则中的限制。您可以将表达式结果分配给变量,并将变量传递到调用中,也可以强制转换表达式

    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;
            }
        });
    }
void测试(){
List lb=new ArrayList();
List lc=new ArrayList();

可流动的((列表行
a
应为
Iterable@Holger谢谢,我不太明白为什么Java 8在第b行出现错误,而Java 6在第b行没有出现错误。你能给我一些提示吗?我也不明白。规则非常复杂,并且由于合并了目标类型而发生了更改。但是由于没有可用的目标类型在这一点上,我希望它的行为类似于Java6。
    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;
            }
        });
    }