lambda表达式中的错误返回类型
以下代码在IntelliJ和Eclipse中编译良好,但JDK编译器1.8.0_25抱怨。 一,代码。
import java.util.function.Predicate; public abstract class MyStream { static MyStream create() { return null; } abstract MyStream filter(MyPredicate predicate); public interface MyPredicate extends Predicate { @Override boolean test(T t); } public void demo() { MyStream. create().filter(b -> b); MyStream. create().filter(s -> s != null); } }
javac 1.8.0_25的输出是:
MyStream.java:18: error: incompatible types: incompatible parameter types in lambda expression MyStream. create().filter(b -> b); ^ MyStream.java:18: error: incompatible types: bad return type in lambda expression MyStream. create().filter(b -> b); ^ ? super Boolean cannot be converted to boolean MyStream.java:19: error: bad operand types for binary operator '!=' MyStream. create().filter(s -> s != null); ^ first type: ? super String second type: MyStream.java:19: error: incompatible types: incompatible parameter types in lambda expression MyStream. create().filter(s -> s != null); ^ Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 4 errors
当我更换? super E
简单E
? super E
,JDK编译成功。
当我替换filter(MyPredicate
with filter(Predicate
,JDK编译成功)。
由于它适用于JDK 1.8.0_60,我怀疑它是一个编译器错误。
有关导致此问题以及何时修复的详细信息?
如果lambda表达式出现在带有通配符的目标类型中(在大多数情况下)
Consumer super Boolean> consumer = b->{...}
问题出现了 – lambda表达式的类型是什么; 特别是b
的类型。
当然,由于通配符,可能会有很多选择; 例如,我们可以明确选择
Consumer super Boolean> consumer = (Object b)->{...}
但是,隐含地, b
应该被推断为Boolean
。 这是有道理的,因为消费者无论如何都应该只使用Boolean
。
http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.3
如果T是通配符参数化的函数接口类型并且lambda表达式是隐式类型的,则地面目标类型是T的非通配符参数化
(这可能假设通配符在目标类型上使用了正确的方差;如果假设不成立,我们可能会发现一些有趣的例子)
super E>
super E>
包含Object
,它不是Boolean
。 即
MyPredicate super E>
可能是一个
MyPredicate
并且您不能将Object
作为boolean
返回。
尝试将lambda更改为:
MyStream. create().filter(b -> Boolean.TRUE.equals(b));
这将无错误地编译和执行,无论流的类型如何,但对于true
Boolean
值的元素将返回true
。