来自 Lambda 表达式的有效 void Return 语句(示例:Runnable)
Valid void Return Statements from Lambda Expressions (Example: Runnable)
在 Java 中看到一些关于 void
return 类型的功能接口的奇怪行为。
有人可以解释为什么下面的 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;
}
}
/* But for some reason, this is totally acceptable. Why? */
Runnable task5 = () -> counter++;
Runnable task6 = () -> ++counter;
因为两个任务return无效。 counter++;
和 ++counter
是结果将被丢弃的操作。此外,其中 none 将被编译器解释为 return counter++;
或 return ++counter;
.
任务 1 和任务 2 由于显而易见的原因无法工作,return 和 int:
Runnable task1 = () -> { return counter; };
Runnable task2 = () -> { return counter + 1;};
任务 3 和任务 4 虽然没有显式 return 和 int,但两者都 return 隐含一个 int:
Runnable task3 = () -> counter;
Runnable task4 = () -> counter + 1;
任务 1 和任务在语义上与任务 3 和任务 4 相同,只是语法糖。
在任务1和任务2中,() -> { return counter; };
和() -> { return counter + 1;};
是语句lambda,可以用表达式lambda () -> counter;
代替和() -> counter + 1;
,分别
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 主体未使用与简单表达式语句完全相同的规则进行验证。
换句话说,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()
全等的生成表达式。具体来说,task8
不接受输入但产生结果;它甚至与任何一元运算符功能接口都不兼容。
用这两个功能接口理解概念的例子:
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
虽然 Runnable 是一个功能接口,就像第一个 (1) 示例一样,这就是为什么不能有像
这样的 return 语句的原因
Runnable ref4 = () -> counter=counter+1; // equivalent to counter++ & ++counter without return statement
But not like
Runnable ref5 = () -> counter; // equivalent to return statement
Runnable ref6 = () -> {return counter;}; // equivalent to return statement
在 Java 中看到一些关于 void
return 类型的功能接口的奇怪行为。
有人可以解释为什么下面的 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;
}
}
/* But for some reason, this is totally acceptable. Why? */ Runnable task5 = () -> counter++; Runnable task6 = () -> ++counter;
因为两个任务return无效。 counter++;
和 ++counter
是结果将被丢弃的操作。此外,其中 none 将被编译器解释为 return counter++;
或 return ++counter;
.
任务 1 和任务 2 由于显而易见的原因无法工作,return 和 int:
Runnable task1 = () -> { return counter; };
Runnable task2 = () -> { return counter + 1;};
任务 3 和任务 4 虽然没有显式 return 和 int,但两者都 return 隐含一个 int:
Runnable task3 = () -> counter;
Runnable task4 = () -> counter + 1;
任务 1 和任务在语义上与任务 3 和任务 4 相同,只是语法糖。
在任务1和任务2中,() -> { return counter; };
和() -> { return counter + 1;};
是语句lambda,可以用表达式lambda () -> counter;
代替和() -> counter + 1;
,分别
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 主体未使用与简单表达式语句完全相同的规则进行验证。
换句话说,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()
全等的生成表达式。具体来说,task8
不接受输入但产生结果;它甚至与任何一元运算符功能接口都不兼容。
用这两个功能接口理解概念的例子:
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
虽然 Runnable 是一个功能接口,就像第一个 (1) 示例一样,这就是为什么不能有像
这样的 return 语句的原因Runnable ref4 = () -> counter=counter+1; // equivalent to counter++ & ++counter without return statement
But not like
Runnable ref5 = () -> counter; // equivalent to return statement
Runnable ref6 = () -> {return counter;}; // equivalent to return statement