java - 来自 Lambda 表达式的有效 void 返回语句(示例 : Runnable)

标签 java lambda runnable unary-operator

使用 void 在 Java 中看到一些关于函数式接口(interface)的奇怪行为返回类型。
有人可以解释为什么 task5 的声明和 task6下面编译?

public class Test {

    private static int counter;

    private static void testRunnable() {
        /* Runnable has a void return type so the following won't compile.
        * Error message is Void methods cannot return a value. (Java 67108969) Makes sense... */
        // Runnable task1 = () -> { return counter; };
        // Runnable task2 = () -> { return counter + 1; };
        // Runnable task3 = () -> counter;
        // Runnable task4 = () -> counter + 1;

        /* But for some reason, this is totally acceptable. Why? */
        Runnable task5 = () -> counter++;
        Runnable task6 = () -> ++counter;
    }
}

最佳答案

lambda 表达式 () -> counter++;有效为 counter++;是一个语句表达式。 JLS 中明确允许这样做。 :

If the function type's result is void, the lambda body is either a statement expression (§14.8) or a void-compatible block.


对于 statement expression's definition :

An expression statement is executed by evaluating the expression; if the expression has a value, the value is discarded.


如果您阅读整个 JLS 15.27.3,您会明白为什么 () -> {return counter + 1;}不是 void 兼容的。 lambda body 没有使用与简单表达式语句完全相同的规则进行验证。
换句话说,counter++;++counter;是语句表达式,这意味着表达式可以被评估并被视为其结果被简单地丢弃的语句。
转换为 block 体时会更清晰(或者看起来更熟悉):
Runnable task5 = () -> {
    counter++; //result discarded, but you can't use "return counter++;"
};
Runnable task6 = () -> {
    ++counter; //result discarded, but you can't use "return ++counter;"
};

这与 UnaryOperator 无关,至少就该功能接口(interface)而言。恰好counter++IntUnaryOperator 兼容,但表达式可能是其他任何内容,包括(但不限于)以下内容,并且您的问题仍然适用,因为该语句会产生结果:
Runnable task5 = () -> counter += 1;
Runnable task6 = () -> counter = counter + 1;
Runnable task7 = () -> Math.addExact(counter, 1); // no change in counter
Runnable task8 = () -> return2(); //return2 takes no input
所有这些都是与 Runnable.run() 一致的产生 int 的表达式。 .具体来说,task8不接受输入但产生结果;它甚至不兼容任何一元运算符功能接口(interface)。

关于java - 来自 Lambda 表达式的有效 void 返回语句(示例 : Runnable),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66587852/

相关文章:

java.lang.reflect.InaccessibleObjectException : Unable to make field private final java. lang.Object java.util.Optional.value 可访问:

java - 与第三方类(class)时的mockito

java - 获取 CompletableFuture.supplyAsync 的结果

python - 在 Python 中使用 lambda 进行延迟评估

android - 显示对话框几秒钟

java - 接口(interface)有两个不同的实现在不同的线程上执行

java - 为什么在 public void run() 中这里不需要 try-catch?

java - SimpleXML 问题

java - HttpGet 的 SSL 问题可能是因为服务器正在请求客户端身份验证

java - 如何将 Modelmapper Converter 重写为 Lambda 表达式 (java 1.8)?