Why doesn't for-each method in java not throw an exception when a Function type argument is passed instead of Consumer?

Sudhanshu Jaisani :

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
ernest_k :

Regarding why the first line works: there's an explanation in the specification:

Generally speaking, a lambda of the form () -> expr, where expr 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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=90187&siteId=1