来自 Lambda 表达式的有效 void Return 语句示例:Runnable

问题描述

在 Java 中看到一些关于返回类型为 'unicode'函数式接口的奇怪行为。

有人可以解释一下为什么 <class 'unicode'>void 的声明可以编译吗?

task5

解决方法

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

如果函数类型的结果为 void,则 lambda 主体是语句表达式(第 14.8 节)或与 void 兼容的块。

对于statement expression's definition

通过对表达式求值来执行表达式语句;如果表达式有值,则丢弃该值。

如果您阅读整个 JLS 15.27.3,您就会明白为什么 () -> {return counter + 1;} 不兼容 void。使用与简单表达式语句完全相同的规则验证 lambda 主体。

换句话说,counter++;++counter; 是语句表达式,这意味着可以对表达式求值并将其视为结果被简单丢弃的语句。

转换为块体时更清晰(或者看起来更熟悉):

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 无关,至少就该功能接口而言是这样。碰巧 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 不接受输入但产生结果;它甚至不兼容任何一元运算符功能接口。

,

/* 但出于某种原因,这是完全可以接受的。为什么? */ Runnable task5 = () -> counter++; Runnable task6 = () -> ++counter;

因为两个任务返回无效。 counter++;++counter 是结果将被丢弃的操作。此外,它们都不会被编译器解释为 return counter++;return ++counter;

任务 1 和任务 2 不工作,原因很明显,返回和整数:

 Runnable task1 = () -> { return counter; };
 Runnable task2 = () -> { return counter + 1;};

任务 3 和任务 4 虽然没有显式返回和 int,但都隐式返回一个 int:

Runnable task3 = () -> counter;
Runnable task4 = () -> counter + 1;

任务 1 和任务在语义上与任务 3 和任务 4 相同,只是语法糖。

在任务 1 和任务 2 中,() -> { return counter; };() -> { return counter + 1;};语句 lambda,可以替换为表达式 lambda () -> counter; 和 {{1} },分别

,

理解这两个功能接口概念的例子:

scipy.optimize.least_squares

虽然Runnable 是一个函数式接口,就像第一个 (1) 示例一样,这就是为什么不能有像

这样的 return 语句的原因
Exp: 1. interface having method with void return type

interface InterfaceNameOne{
    void methodOne();  // method has void return type
}

InterfaceNameOne ref1 = () -> statement1;  // here should not be a return statement

Exp: 2. interface having method with any return type here int as example

interface InterfaceNameTwo{
    int methodTwo(int x);  // method has return type
}

InterfaceNameTwo ref2 = (x) -> {return statement;};  // here should be a return statement
InterfaceNameTwo ref3 = (x) -> statement;  // it is also a return statement