最好在代码中表达这种行为:
List<Integer> list= new ArrayList<>();
Stream.of(1,2,3).forEach(i -> list.add(1)); // COMPILES
Stream.of(1,2,3).forEach(i -> true); // DOES NOT COMPILE!
forEach(...)
接受 Consumer
,但如果 List 接口(interface)具有以下签名,为什么第一个示例会编译 boolean add(E e)
?而第二个产量:
bad return type in lambda expression: boolean cannot be converted to
void
虽然你可能只是在寻找
Stream.of(1,2,3).forEach(list::add); // adding all to `list`
why does the first example compile if List interface has following
signature boolean add(E e)
主要是因为在第一次调用时忽略了方法的返回类型。这就是它扩展到的内容:
Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
list.add(1); // ignored return type
}
}); // COMPILES
另一方面,另一种 lambda 表示更像是一个 Predicate
(也是一个 FunctionalInterface
),表示总是返回 true
从它的 test
方法。如果您甚至尝试将其表示为 Consumer
,它可能看起来就像
Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
return true; // you can correlate easily now why this wouldn't compile
}
}); // DOES NOT COMPILE!
添加到 design basis via a comment from Brian
Java allows you to call a method and ignore the return value (a method invocation expression as a statement). Since we allow this at
the invocation, we also allow this when adapting a method to a
functional interface whose arguments are compatible but the functional
interface is void-returning.
编辑:将其放入his own words尽可能靠近 language spec :
More precisely, list.add(x)
is a statement expression, and
therefore is void-compatible. true
is not a statement expression,
and therefore not void-compatible. forEach(Consumer)
requires a
void-compatible lambda.