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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33085151/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:18:03  来源:igfitidea点击:

bad return type in lambda expression

javalambdajava-8

提问by Roland Illig

The following code compiles fine in IntelliJ and Eclipse, but the JDK compiler 1.8.0_25 complains. First, the code.

以下代码在 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);
  }
}

The output from javac 1.8.0_25 is:

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

When I replace ? super Ewith simply E, JDK compiles successfully.

当我用simple替换? super EE,JDK 编译成功。

When I replace filter(MyPredicatewith filter(Predicate, JDK compiles successfully.

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

Since it works with JDK 1.8.0_60, I suspect it is a compiler bug.

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

Any details on what caused this and when it has been fixed?

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

采纳答案by ZhongYu

If a lambda expression appears in a target type with wildcards (as in most cases)

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

  Consumer<? super Boolean> consumer = b->{...}

the question arises - what's the type of the lambda expression; in particular, the type of b.

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

Of course, there could be many choices due to the wildcards; e.g. we could explicitly choose

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

  Consumer<? super Boolean> consumer = (Object b)->{...}

However, implicitly, bshould be inferred as Boolean. This makes sense since the consumer should only be fed with Booleananyway.

但是,隐含地,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

If T is a wildcard-parameterized functional interface type and the lambda expression is implicitly typed, then the ground target type is the non-wildcard parameterization of T

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

(This probably assumes that wildcards are use properly variance-wise on the target type; we might find some hilarious examples if the assumption doesn't hold)

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

回答by Bohemian

<? super E>includes Object, which isn't a Boolean. ie

<? super E>包括Object,它不是Boolean. IE

MyPredicate<? super E>

Could be a

可能是一个

MyPredicate<Object>

and you can't return an Objectas a boolean.

并且您不能将 anObject作为boolean.

Try changing your lambda to:

尝试将您的 lambda 更改为:

MyStream.<Boolean> create().filter(b -> Boolean.TRUE.equals(b));

which will compile and execute without error not matter the type of the stream, but will return truefor elements that are trueBooleanvalues.

无论流的类型如何,它都会编译和执行而不会出错,但会返回值的true元素trueBoolean