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

Popular posts from this blog

Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12:test (default-test) on project.Error occurred in starting fork -

windows - Debug iNetMgr.exe unhandle exception System.Management.Automation.CmdletInvocationException -

unity3d - Fatal error- Monodevelop-Unity failed to start -