Why do Consumers accept lambdas with statement bodies but not expression bodies?

前端 未结 3 1121
不知归路
不知归路 2020-11-27 15:13

The following code surprisingly is compiling successfully:

Consumer p = \"\"::equals;

This too:

p = s -> \         


        
3条回答
  •  攒了一身酷
    2020-11-27 15:55

    s -> "".equals(s)
    

    and

    s -> true
    

    don't rely on same function descriptors.

    s -> "".equals(s) may refer either String->void or String->boolean function descriptor.
    s -> true refers to only String->boolean function descriptor.

    Why ?

    • when you write s -> "".equals(s), the body of the lambda : "".equals(s) is a statement that produces a value.
      The compiler considers that the function may return either void or boolean.

    So writing :

    Function function = s -> "".equals(s);
    Consumer consumer = s -> "".equals(s);
    

    is valid.

    When you assign the lambda body to a Consumer declared variable, the descriptor String->void is used.
    Of course, this code doesn't make much sense (you check the equality and you don't use the result) but the compiler doesn't care.
    It is the same thing when you write a statement : myObject.getMyProperty() where getMyProperty() returns a boolean value but that you don't store the result of it.

    • when you write s -> true, the body of the lambda : true is a single expression .
      The compiler considers that the function returns necessarily boolean.
      So only the descriptor String->boolean may be used.

    Now, come back to your code that doesn't compile.
    What are you trying to do ?

    Consumer p = s -> true;
    

    You cannot. You want to assign to a variable that uses the function descriptor Consumer a lambda body with the String->void function descriptor. It doesn't match !

提交回复
热议问题