【问题标题】:lambda expression for Consumer Interface with return type具有返回类型的消费者接口的 lambda 表达式
【发布时间】:2019-09-15 16:15:24
【问题描述】:

我不太明白的是为什么 java 编译器允许在消费者接口中使用 lambda 表达式,例如 s -> s.isEmpty()

我已经为消费者接口尝试了一个像 s -> s.isEmpty() 这样的 lambda 表达式,它可以正常工作。其他一些 lambda 表达式不起作用,因为它们返回一些东西,例如 s -> s

Consumer<String> cons1 = s -> s.isEmpty();
cons1.accept("abc");

编译和执行没有问题。

所以我遇到的问题是我认为像 s -&gt; s.isEmpty() 这样的 lambda 表达式总是等价于 s -&gt; {return s.isEmpty()};,所以我期待编译器给我一个错误,因为你不能返回 boolean(或任何其他type) 来自消费者接口。 显然,如果没有 return 语句,编译器会将 lambda 表达式转换为方法,并且方法 isEmpty() 只是被调用而没有实际返回值。 所以问题是什么时候将 return 添加到 lambda 表达式的主体中?这样我就可以知道编译器何时会给出编译器错误以及原因。

非常感谢,如果我解释得不够清楚,我很抱歉,我是新来的。

【问题讨论】:

  • 你到底在问什么?使用Consumer 对象时会调用方法isEmpty()。但是,isEmpty() 的返回值没有被使用,只是被忽略了。
  • 这是因为方法调用表达式可以丢弃返回类型,如果这样可以使其与目标类型兼容。所以s -&gt; s.isEmpty() 等于s -&gt; { return s.isEmpty(); }s -&gt; { s.isEmpty(); return; }
  • s.isEmpty() 是一个声明,s 不是。
  • 如果不允许这样做,您也不能将set.add 用作消费者,因为这将忽略返回类型。您可以忽略返回类型。
  • 你也可以Consumer&lt;String&gt; cons1 = String::isEmpty;,但是没有加return关键字……accept方法的返回类型是void

标签: java lambda functional-interface


【解决方案1】:

specification中有明确的定义,如果lambda的body是一个语句表达式,返回类型为void的结果会被丢弃

15.27.3。 Lambda 表达式的类型

如果 lambda 的主体是语句表达式(即,允许作为语句独立的表达式),它与产生 void 的函数类型兼容;任何结果都被简单地丢弃。因此,例如,以下两个都是合法的:

 //Predicate has a boolean result
   Predicate<String> p = s -> list.add(s);

// Consumer has a void result
   Consumer<String> c = s -> list.add(s);

一般来说,() -&gt; expr 形式的 lambda(其中 expr 是语句表达式)被解释为 () -&gt; { return expr; }() -&gt; { expr; },具体取决于目标类型。

【讨论】:

    【解决方案2】:

    FunctionalInterface 中定义的单个抽象方法的返回类型定义了推断 lambda 的方式。例如,共享示例中的Consumer&lt;String&gt; 可以表示为匿名类,例如:

    // 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&lt;String&gt; 时可以转换为匿名类,例如:

    // Predicate<String> predicate = s -> s.isEmpty();
    Predicate<String> predicate = new Predicate<String>() {
        @Override
        public boolean test(String s) {
            return s.isEmpty(); // returns boolean here
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-06
      • 2019-05-09
      • 2018-10-09
      • 2021-05-18
      • 2021-11-01
      • 1970-01-01
      • 2019-04-20
      相关资源
      最近更新 更多