我不太了解的是,为什么Java编译器在使用者接口中允许使用lambda表达式,例如s -> s.isEmpty()
。
我已经尝试过使用s -> s.isEmpty()
这样的lambda表达式作为Consumer接口,它可以正常工作。其他一些lambda表达式不起作用,因为它们返回了某些内容,例如s -> s
。
Consumer<String> cons1 = s -> s.isEmpty();
cons1.accept("abc");
编译并执行没有问题。
所以我的问题是我认为lambda表达式(例如s -> s.isEmpty()
总是与s -> {return s.isEmpty()};
等效,因此我期望编译器给我一个错误,因为您无法返回{{1 }}(或其他任何类型)的使用者接口。
显然,如果没有return语句且仅在不实际返回值的情况下调用方法boolean
,则编译器会将lambda表达式转换为方法。
所以问题是何时将返回值添加到lambda表达式的主体?这样一来,我就可以知道编译器何时会给出编译器错误以及原因。
非常感谢,如果我对自己的解释不够好,我很抱歉,我是新来的。
答案 0 :(得分:4)
在specification中有明确定义,如果lambda的主体是语句表达式,则返回类型为void时,结果将被丢弃
如果lambda的主体是语句表达式(即允许作为语句独立存在的表达式),则它与产生空隙的函数类型兼容;任何结果都将被简单丢弃。因此,例如,以下两项都是合法的:
//Predicate has a boolean result
Predicate<String> p = s -> list.add(s);
// Consumer has a void result
Consumer<String> c = s -> list.add(s);
一般来说,形式为
() -> expr
的lambda(其中expr是语句表达式)根据目标类型被解释为() -> { return expr; }
或() -> { expr; }
。
答案 1 :(得分:2)
在FunctionalInterface
中定义的单个抽象方法的返回类型定义了lambda的推断方式。例如,共享示例中的Consumer<String>
可以表示为匿名类,例如:
// Consumer<String> consumer = s -> s.isEmpty();
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
s.isEmpty(); // treated as void here
}
};
相同的lambda表达式表示为Predicate<String>
时,可以转换为匿名类,例如:
// Predicate<String> predicate = s -> s.isEmpty();
Predicate<String> predicate = new Predicate<String>() {
@Override
public boolean test(String s) {
return s.isEmpty(); // returns boolean here
}
};