消费者为什么接受语句体而不是表达体的lambdas? [英] Why do Consumers accept lambdas with statement bodies but not expression bodies?
问题描述
以下代码令人惊讶地成功编译:
The following code surprisingly is compiling successfully:
Consumer<String> p = ""::equals;
这也是:
p = s -> "".equals(s);
但这是失败的,错误 boolean无法转换为void
符合预期:
But this is fails with the error boolean cannot be converted to void
as expected:
p = s -> true;
使用括号修改第二个示例也失败:
Modification of the second example with parenthesis also fails:
p = s -> ("".equals(s));
这是Java编译器中的错误还是我不知道的类型推断规则?
Is it a bug in Java compiler or is there a type inference rule I don't know about?
推荐答案
首先,值得看一下消费者< String>
实际上是。 来自文档:
First, it's worth looking at what a Consumer<String>
actually is. 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.
所以这是一个接受a的函数字符串并且不返回任何内容。
So it's a function that accepts a String and returns nothing.
Consumer<String> p = ""::equals;
编译成功,因为等于
可以带一个字符串(事实上,任何对象)。等于的结果只是被忽略。*
Compiles successfully because equals
can take a String (and, indeed, any Object). The result of equals is just ignored.*
p = s -> "".equals(s);
这完全相同,但语法不同。编译器知道不添加隐式 return
,因为 Consumer
不应返回值。如果lambda是函数< String,Boolean>
,将 添加隐式返回
但是。
This is exactly the same, but with different syntax. The compiler knows not to add an implicit return
because a Consumer
should not return a value. It would add an implicit return
if the lambda was a Function<String, Boolean>
though.
p = s -> true;
这需要一个字符串( s
)但是因为 true
是表达式而不是语句,所以不能以相同的方式忽略结果。编译器必须添加隐式返回
,因为表达式本身不能存在。因此,这个 有一个返回:一个布尔值。因此,它不是消费者
。**
This takes a String (s
) but because true
is an expression and not a statement, the result cannot be ignored in the same way. The compiler has to add an implicit return
because an expression can't exist on its own. Thus, this does have a return: a boolean. Therefore it's not a Consumer
.**
p = s -> ("".equals(s));
同样,这是表达式,而非声明。暂时忽略lambdas,你会看到行 System.out.println(Hello);
同样无法编译,如果你把它包装在括号中。
Again, this is an expression, not a statement. Ignoring lambdas for a moment, you will see the line System.out.println("Hello");
will similarly fail to compile if you wrap it in parentheses.
*来自规范:
如果身体lambda是一个语句表达式(也就是说,允许独立作为语句的表达式),它与产生void的函数类型兼容;任何结果都会被丢弃。
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.
**From the spec (thanks, Eugene):
lambda表达式与[void-producing]函数类型if一致。 ..
lambda body是一个语句表达式
(§14.8)
或无效兼容块。
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.
这篇关于消费者为什么接受语句体而不是表达体的lambdas?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!