以下代码在 IntelliJ 和 Eclipse 中可以正常编译,但 JDK 编译器 1.8.0_25 会报错。首先,代码。
import java.util.function.Predicate;
public abstract class MyStream<E> {
static <T> MyStream<T> create() {
return null;
}
abstract MyStream<E> filter(MyPredicate<? super E> predicate);
public interface MyPredicate<T> extends Predicate<T> {
@Override
boolean test(T t);
}
public void demo() {
MyStream.<Boolean> create().filter(b -> b);
MyStream.<String> create().filter(s -> s != null);
}
}
javac 1.8.0_25 的输出是:
MyStream.java:18: error: incompatible types: incompatible parameter types in lambda expression
MyStream.<Boolean> create().filter(b -> b);
^
MyStream.java:18: error: incompatible types: bad return type in lambda expression
MyStream.<Boolean> create().filter(b -> b);
^
? super Boolean cannot be converted to boolean
MyStream.java:19: error: bad operand types for binary operator '!='
MyStream.<String> create().filter(s -> s != null);
^
first type: ? super String
second type: <null>
MyStream.java:19: error: incompatible types: incompatible parameter types in lambda expression
MyStream.<String> create().filter(s -> s != null);
^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
4 errors
当我更换时? super E
简单地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 http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.3
如果 T 是通配符参数化函数接口类型并且 lambda 表达式是隐式类型的,则基本目标类型是 T 的非通配符参数化
(这可能假设通配符在目标类型上正确使用方差;如果假设不成立,我们可能会发现一些搞笑的例子)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)