以下代码在IntelliJ和Eclipse中编译良好,但JDK编译器1.8.0_25抱怨。首先是代码。
$('.modal-toggle').click(function(e){
var tab = e.target.hash;
$('li > a[href="' + tab + '"]').tab("show");
});
javac 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);
}
}
当我用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
时,JDK编译成功。
当我用E
替换filter(MyPredicate
时,JDK编译成功。
由于它适用于JDK 1.8.0_60,我怀疑它是编译器错误。
有关导致此问题及修复时间的详细信息?
答案 0 :(得分:9)
如果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的非通配符参数化
(这可能假设通配符在目标类型上使用了正确的方差;如果假设不成立,我们可能会发现一些有趣的例子)
答案 1 :(得分:1)
<? super E>
包含Object
,其中不是Boolean
。即
MyPredicate<? super E>
可能是
MyPredicate<Object>
并且您无法将Object
作为boolean
返回。
尝试将lambda更改为:
MyStream.<Boolean> create().filter(b -> Boolean.TRUE.equals(b));
将无错误地编译和执行,无论流的类型如何,但对于true
true
值的元素将返回Boolean
。