java - 为什么带有返回类型的 Java 方法引用与 Consumer 接口(interface)匹配?

标签 java java-8

我对以下代码感到困惑

class LambdaTest {
    public static void main(String[] args) {
        Consumer<String>         lambda1 = s -> {};
        Function<String, String> lambda2 = s -> s;

        Consumer<String>         lambda3 = LambdaTest::consume; // but s -> s doesn't work!
        Function<String, String> lambda4 = LambdaTest::consume;
    }

    static String consume(String s) { return s;}
}

我本来预计 lambda3 的分配会失败,因为我的消耗方法与使用者接口(interface)中的接受方法不匹配 - 返回类型不同,字符串与 void。

此外,我一直认为 Lambda 表达式和方法引用之间存在一对一的关系,但正如我的示例所示,这显然不是这种情况。

有人可以向我解释这里发生了什么吗?

最佳答案

Brian Goetz指出in a comment ,设计决策的基础是允许以与调用方法相同的方式使方法适应功能接口(interface),即您可以调用每个值返回方法并忽略返回值。

当涉及到 lambda 表达式时,事情变得有点复杂。有两种形式的 lambda 表达式,(args) -> expression(args) -> { statements* } .

第二种形式是否为void兼容,取决于是否没有代码路径尝试返回值的问题,例如() -> { return ""; }不是 void兼容,但表达式兼容,而 () -> {}() -> { return; }void兼容的。请注意 () -> { for(;;); }() -> { throw new RuntimeException(); }两者都是,void兼容和价​​值兼容,因为它们不能正常完成并且没有 return陈述。

表格(arg) -> expression如果表达式计算为一个值,则值兼容。但也有表达式,它们同时是语句。这些表达式可能有副作用,因此可以编写为仅产生副作用的独立语句,而忽略产生的结果。同样,表格 (arg) -> expression可以是void兼容,如果表达式也是一个语句。
s -> s 形式的表达式不能是 void兼容 s不是陈述,即你不能写 s -> { s; }任何一个。另一方面s -> s.toString()可以是void兼容,因为方法调用是语句。同样,s -> i++可以是void compatible as 增量可以用作语句,所以s -> { i++; }也是有效的。当然,i必须是一个字段才能工作,而不是局部变量。

Java 语言规范 §14.8. Expression Statements列出所有可用作语句的表达式。除了已经提到的方法调用和递增/递减运算符之外,它还命名了赋值和类实例创建表达式,所以 s -> foo=ss -> new WhatEver(s)void也兼容。

作为旁注,表格(arg) -> methodReturningVoid(arg)是唯一不值兼容的表达式形式。

关于java - 为什么带有返回类型的 Java 方法引用与 Consumer 接口(interface)匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37308294/

相关文章:

java - 如何使用 jOOQ 获取事务内部的底层连接?

java - 用日期强制 TimSort IllegalArgumentException

java - Storm 拓扑的 bolt 接收重复结果

java.lang.IllegalStateException : Could not execute method of the activity (trying to send a mail)

java - Android 应用程序中的条件语句未按预期工作

java - Java 8 lambda 是否被编译为内部类、方法或其他东西?

java - 时间与日期与日历java

java - 有没有办法在没有实体的情况下使用 `@Procedure` 注释?

java - 集合排序(空列表()): cannot infer type-variable

java - 现代 Java 实践中有关 java 流 dropWhile 示例的问题