13

I was curious why a lambda with a return type can not be casted to a Runnable whereas a non void method reference can.

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
flakes
  • 21,558
  • 8
  • 41
  • 88

2 Answers2

15

The Runnable interface defines the run method with return type void. In a lambda expression that means that the part following the arrow -> must be a statement. This is explained in JLS §15.27.3:

If the function type's result is void, the lambda body is either a statement expression (§14.8) or a void-compatible block.

The JLS $14.5 clearly defines the syntax of a statement. As explained above it must be an "ExpressionStatement" (§ 14.8). Looking there, you can find that a simple literal is not an adequate expression, but a method invocation is (even if it returns something).

Seelenvirtuose
  • 20,273
  • 6
  • 37
  • 66
  • 1
    Could you point where in the JLS is mentioned that, in that case, "the part following the arrow `->` must be a _statement_"? I'm looking for it. – Tunaki Apr 18 '16 at 14:39
  • 2
    @Tunaki Found it, it's [§15.27.3](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.3). – RealSkeptic Apr 18 '16 at 14:57
  • 1
    @RealSkeptic Ha perfect indeed: *If the function type's result is void, the lambda body is either a statement expression (§14.8) or a void-compatible block.* And a primary expression isn't a statement expression (and isn't a block). – Tunaki Apr 18 '16 at 14:59
  • @RealSkeptic Wow. Thanks for finding it out. I will add this info to my answer (with your agreement). – Seelenvirtuose Apr 19 '16 at 05:49
1

This is not really a “special” rule for Lambdas. It has always been acceptable to use a non-void method in a statement context (in which case, the return value is thrown away), but not so with a simple expression. For instance “String.valueOf(true);” is a valid java statement, that may occupy a line by itself, whereas “true;” is not and may not.