问题描述
在 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