java - 为什么消费者接受带有语句体而不是表达式体的 lambda?

标签 java lambda java-8 type-inference

以下代码居然编译成功了:

Consumer<String> p = ""::equals;

这也是:

p = s -> "".equals(s);

但这失败了,错误 boolean cannot be convert to void as expected:

p = s -> true;

用括号修改第二个例子也失败了:

p = s -> ("".equals(s));

这是 Java 编译器中的错误还是我不知道的类型推断规则?

最佳答案

首先,有必要看看 Consumer<String> 是什么实际上是。 From the documentation :

Represents an operation that accepts a single input argument and returns no result. Unlike most other functional interfaces, Consumer is expected to operate via side-effects.

所以它是一个接受字符串并且不返回任何内容的函数。

Consumer<String> p = ""::equals;

编译成功,因为 equals可以接受一个字符串(实际上,任何对象)。 equals 的结果会被忽略。*

p = s -> "".equals(s);

这完全一样,但语法不同。编译器知道不添加隐式 return因为一个 Consumer不应返回值。它添加一个隐含的 return如果 lambda 是 Function<String, Boolean>不过。

p = s -> true;

这需要一个字符串 ( s ) 但因为 true是表达式而不是语句,结果不能以同样的方式忽略。编译器必须添加一个隐式 return因为表达式不能单独存在。因此,这个确实有一个返回值:一个 boolean 值。因此它不是 Consumer .**

p = s -> ("".equals(s));

同样,这是一个表达式,而不是一个语句。暂时忽略 lambda,您将看到 System.out.println("Hello"); 行如果将其括在括号中,同样将无法编译。


*来自 the spec :

If the body of a lambda is a statement expression (that is, an expression that would be allowed to stand alone as a statement), it is compatible with a void-producing function type; any result is simply discarded.

**来自 the spec (谢谢,Eugene):

A lambda expression is congruent with a [void-producing] function type if ... the lambda body is either a statement expression (§14.8) or a void-compatible block.

关于java - 为什么消费者接受带有语句体而不是表达式体的 lambda?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45460896/

相关文章:

java - 在同一连接上进行 Web 服务调用

java - 从 ListView 中隐藏/显示 ImageView

java - 在 RxKotlin/RxJava 中使用 BehaviourSubject 惯用地创建热可观察对象

c# - 预期的方法名称 - 使用 lambda 表达式错误?

c# - 如何在 C# 中使用 lambda 表达式检测元素是否存在?

java - 如何判断是否安装了 JRE 或 JDK

java - 使用函数进行bean比较的库函数?

java - 错误: Unresolved compilation problem: RetailItem cannot be resolved to a variable

java - 使用 Java Lambda 创建两个(或更多)列表的笛卡尔积集合

Java 流 API : are there syntax sugar for identity functor?