以下代码居然编译成功了:
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.
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/