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

时间:2015-10-12 15:45:33

标签: java lambda java-8

以下代码在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,我怀疑它是编译器错误。

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

2 个答案:

答案 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