Mak*_*rat 8 java foreach lambda functional-programming java-8
根据我对java 8 lambda表达式的理解,如果我们在花括号中不包含" - >"之后的代码,那么将隐式返回该值.但是在下面的示例中,forEach方法expect Consumer和expression返回值,但编译器没有在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 a value
messages.stream().forEach(s-> s.toString()); // works fine
messages.stream().forEach(s-> {return s.append("helloworld");}); // doesn't work , Void methods cannot return a value
messages.stream().forEach((StringBuilder s)-> {return s.append("helloworld");}); // doesn't work , Void methods cannot return a value
Run Code Online (Sandbox Code Playgroud)
s.append返回StringBuilder并s.toString()返回,String但lambda将其视为void.
我在这里错过了什么?当我们在对象上调用方法时,为什么编译器没有给出错误?
Era*_*ran 12
如果满足以下所有条件,则lambda表达式与函数类型一致:
函数类型没有类型参数.
lambda参数的数量与函数类型的参数类型的数量相同.
如果显式键入lambda表达式,则其形式参数类型与函数类型的参数类型相同.
如果假设lambda参数与函数类型的参数类型具有相同的类型,则:
如果函数类型的结果为void,则lambda主体是语句表达式(第14.8节)或与void兼容的块.
如果函数式的结果是一个(非空)类型R,然后或者i)所述拉姆达体是其中R兼容在赋值上下文,或ii)在lambda体是值兼容块,并且每个表达式结果表达式(第15.27.2节)与赋值上下文中的R兼容.
上面突出显示的句子意味着任何语句lambda表达式(即没有块的lambda表达式)匹配单个方法的返回类型所在void的Consumer功能接口(例如forEach方法所需的功能接口).
这解释了为什么s.append("helloworld")&s.toString()(你的1,2和4个例子)作为语句lambda表达式正常工作.
示例5和6不起作用,因为它们具有块lambda体,它们是与值兼容的lambda表达式.要成为void-compatible,所有的返回语句都必须返回任何内容(即只是return;).
另一方面,以下void-compatible块lambda体将通过编译:
messages.stream().forEach(s-> {s.append("helloworld");});
messages.stream().forEach(s-> {s.append("helloworld"); return;});
Run Code Online (Sandbox Code Playgroud)
您的第4个示例 - messages.stream().forEach(s-> s);由于以下方法未通过编译而导致的原因不同:
void method (StringBuilder s)
{
s;
}
Run Code Online (Sandbox Code Playgroud)
来自java.util.stream.Stream, 的签名forEach是:
void forEach(Consumer<? super T> action)
从java.util.function.Consumer,action必须实现以下方法:
void accept(T t)
在所有不起作用的示例中,您返回的是T,它与 的返回类型不匹配void。
为什么当我们调用对象上的方法时编译器没有给出错误?
因为您没有尝试执行return某些操作,所以 lambda 的返回类型为void,它与所需的Consumer签名匹配。
唯一可能的类型s -> s是T -> T,而(StringBuilder s) -> s.append()可能是StringBuilder -> (),它满足void要求。
| 归档时间: |
|
| 查看次数: |
2481 次 |
| 最近记录: |