lambda表达式中的错误返回类型

Rol*_*lig 11 java lambda java-8

以下代码在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);
  }
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

当我? super E简单地替换时E,JDK编译成功.

当我替换filter(MyPredicatefilter(Predicate,JDK编译成功.

由于它适用于JDK 1.8.0_60,我怀疑它是一个编译器错误.

有关导致此问题以及何时修复的详细信息?

Zho*_*gYu 10

如果lambda表达式出现在带有通配符的目标类型中(在大多数情况下)

  Consumer<? super Boolean> consumer = b->{...}
Run Code Online (Sandbox Code Playgroud)

问题出现了 - lambda表达式的类型是什么; 特别是,类型b.

当然,由于通配符,可能会有很多选择; 我们可以明确选择

  Consumer<? super Boolean> consumer = (Object b)->{...}
Run Code Online (Sandbox Code Playgroud)

但是,隐含地,b应该推断为Boolean.这是有道理的,因为消费者Boolean无论如何都应该被喂食.

http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.3

如果T是通配符参数化的函数接口类型并且lambda表达式是隐式类型的,则地面目标类型是T的非通配符参数化

(这可能假设通配符在目标类型上使用了正确的方差;如果假设不成立,我们可能会发现一些有趣的例子)