具有返回类型的使用者接口的lambda表达式

时间:2019-09-15 16:15:24

标签: java lambda functional-interface

我不太了解的是,为什么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表达式的主体?这样一来,我就可以知道编译器何时会给出编译器错误以及原因。

非常感谢,如果我对自己的解释不够好,我很抱歉,我是新来的。

2 个答案:

答案 0 :(得分:4)

specification中有明确定义,如果lambda的主体是语句表达式,则返回类型为void时,结果将被丢弃

15.27.3。 Lambda表达式的类型

如果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
    }
};