Why doesn't forEach
method in java not show a compiler error when a Function type argument is passed instead of Consumer? Here both of the lines are returning a boolean value for every element in the stream but only 2nd line gets a compilation error? Is there any other property of lambda expression for such scenario?
Here's my code:
Stream.of(1,2,3,4).forEach(a->a.equals(1));//line 1
Stream.of(1,2,3,4).forEach(a->{return a.equals(1);});//line 2
Regarding why the first line works: there's an explanation in the specification:
Generally speaking, a lambda of the form
() -> expr
, whereexpr
is a statement expression, is interpreted as either() -> { return expr; }
or() -> { expr; }
, depending on the target type.
The above comes with the following example (good coincidence, this is very similar to your example):
// Consumer has a void result
java.util.function.Consumer<String> c = s -> list.add(s);
This simply means that the compiler ignores the return type for the expression, as though your code were simply this (which is valid for a void method):
Stream.of(1, 2, 3, 4).forEach(a -> {
a.equals(1);
});
And regarding the second line, the spec says:
A block lambda body is void-compatible if every return statement in the block has the form
return;
.
In your case, though, {return a.equals(1);}
does not meet this rule. Void methods don't return a value.
An easy way to understand this is to consider that the compiler applies method body validation rules (such that the body must be compatible with the declaration public void accept(T t)
) - as mentioned in the tutorial