Lambda投射规则

我很好奇为什么带有返回类型的lambda不能被转换为Runnable ,而非void方法引用可以。

 Runnable r1 = () -> 1; // not allowed // error: incompatible types: bad return type in lambda expression // int cannot be converted to void Runnable r2 = ((Supplier)() -> 1)::get; // allowed 

Runnable接口使用返回类型void定义run方法。 在lambda表达式中,这意味着箭头->后面的部分必须是一个语句 。 这在JLS§15.27.3中进行了解释:

如果函数类型的结果为void,则lambda主体是语句表达式(第14.8节)或与void兼容的块。

JLS $ 14.5清楚地定义了语句的语法。 如上所述,它必须是“ExpressionStatement”( §14.8 )。 在那里,您可以发现一个简单的文字不是一个适当的表达式,而是一个方法调用(即使它返回一些东西)。

这对Lambdas来说并不是一个“特殊”规则。 在语句上下文中使用非void方法一直是可以接受的(在这种情况下,抛弃返回值),但使用简单表达式则不然。 例如,“String.valueOf(true);”是一个有效的java语句,它可以单独占用一行,而“true;”不是也可能不是。