Why Java 8 Stream forEach method behaves differently? -
as per understanding of java 8 lambda expressions, if don't include code after "->" in curly braces value returned implicitly. in case of below example, foreach
method expects consumer
, expression returns value compiler not giving error in eclipse.
list<stringbuilder> messages = arrays.aslist(new stringbuilder(), new stringbuilder()); messages.stream().foreach(s-> s.append("helloworld"));//works fine messages.stream().foreach((stringbuilder s)-> s.append("helloworld")); //works fine messages.stream().foreach(s-> s); // doesn't work , void methods cannot return value messages.stream().foreach(s-> s.tostring()); // works fine messages.stream().foreach(s-> {return s.append("helloworld");}); // doesn't work , void methods cannot return value messages.stream().foreach((stringbuilder s)-> {return s.append("helloworld");}); // doesn't work , void methods cannot return value
s.append
returns stringbuilder
, s.tostring()
returns string
lambda treats void
.
what missing here? why isn't compiler giving error when invoke method on object?
from jls 15.27.3. type of lambda expression:
a lambda expression congruent function type if of following true:
the function type has no type parameters.
the number of lambda parameters same number of parameter types of function type.
if lambda expression explicitly typed, formal parameter types same parameter types of function type.
if lambda parameters assumed have same types function type's parameter types, then:
if function type's result void, lambda body either statement expression (§14.8) or void-compatible block.
if function type's result (non-void) type r, either i) lambda body expression compatible r in assignment context, or ii) lambda body value-compatible block, , each result expression (§15.27.2) compatible r in assignment context.
the highlighted sentence above means statement lambda expression (i.e. lambda expression without block) matches functional interface single method's return type void
(such consumer
functional interface required foreach
method).
this explains why s.append("helloworld")
& s.tostring()
(your 1,2 & 4 examples) work fine statement lambda expressions.
examples 5 & 6 don't work, since have block lambda bodies value-compatible lambda expressions. void-compatible
, return statements must return nothing (i.e. return;
).
on other hand, following void-compatible
block lambda bodies pass compilation :
messages.stream().foreach(s-> {s.append("helloworld");}); messages.stream().foreach(s-> {s.append("helloworld"); return;});
your 4th example - messages.stream().foreach(s-> s);
doesn't work same reason following method doesn't pass compilation :
void method (stringbuilder s) { s; }
Comments
Post a Comment