Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果实际参数是lambda,则在重载方法之间进行选择_Java_Lambda_Functional Programming_Java 8 - Fatal编程技术网

Java 如果实际参数是lambda,则在重载方法之间进行选择

Java 如果实际参数是lambda,则在重载方法之间进行选择,java,lambda,functional-programming,java-8,Java,Lambda,Functional Programming,Java 8,在Java 1.8中,以下lambda表达式符合Runnable和Callable功能接口: () -> { throw new RuntimeException("FIXME"); } 不过,如果我使用单参数方法将其提交给,并忽略返回值(即,没有可用的类型推断信息),则在编译时选择,除非我显式地将lambda强制转换为Runnable 在上述情况下,如果Runnable和Callable不共享任何公共层次结构,并且大多数特定的类型规则在此不适用,编译器如何在重载方法之间进行选择

在Java 1.8中,以下lambda表达式符合
Runnable
Callable
功能接口:

() -> {
    throw new RuntimeException("FIXME");
}
不过,如果我使用单参数方法将其提交给,并忽略返回值(即,没有可用的类型推断信息),则在编译时选择,除非我显式地将lambda强制转换为
Runnable

在上述情况下,如果
Runnable
Callable
不共享任何公共层次结构,并且大多数特定的类型规则在此不适用,编译器如何在重载方法之间进行选择?

我相信这是因为
Callable
声明了返回类型,而
Runnable
没有

从JLS部分中,如果有明确的最具体类型,则选择最具体类型的重载。这是关于大多数特定功能接口类型的说明:

对于表达式e,如果T不是S的子类型,且以下情况之一为真,则函数接口类型S比函数接口类型T更具体(其中U1…Uk和R1是S捕获函数类型的参数类型和返回类型,V1…Vk和R2是T函数类型的参数类型和返回类型):

如果e是一个显式类型的lambda表达式(§15.27.1),则以下情况之一为真:

  • R2是空的
T
Runnable
S
Callable
Callable
更具体,因为它的返回类型不是void,因此选择了
Callable

方法重载解析非常复杂,因此可能有一点我遗漏了,但我认为这就是为什么它选择了
Callable

尽管答案是正确的,但lambda机制的另一个方面值得一提

具有块体的lambda分为两类:

问题中的lambda是同时存在的,因为它无法正常完成(由于无条件异常抛出),并且其中的所有
return
语句都是无值的,并且都返回一个值,因为根本没有
return
语句

但是,大多数lambda是一个或另一个。如果lambda仅与
void兼容
,则lambda将仅与
可运行
兼容


稍微违反直觉(但逻辑上正确)的是,即使问题中的lambda从未返回值,它也被归类为“当有
返回时总是返回值”.

@Makoto这正是重载在这里发生的原因。@biziclop:我不确定为什么会有一秒钟将覆盖和重载混在一起。一定是天气原因。奇怪的是,我的示例代码选择了
可运行的
重载。一个示例演示了事情有多奇怪。这似乎是异常抛出来摆动它。@biziclop:这没什么奇怪的。一个形式为
()->{}
的lambda表达式,没有
返回值;
语句(也没有
抛出
)是
void
-兼容的,因为它正常完成而不返回值,因此它不能是
可调用的
。相反,不正常完成的lambda表达式可以是值兼容的。您可以对
()->{while(true);}执行相同的操作
这不是正常完成的。请看,我认为您应该补充一点,OP中的lambda表达式被认为是显式类型的,因为它没有参数。@Real怀疑论者:
call
run
都不需要参数,那么如何使一个表达式比另一个表达式更显式类型化呢?事情似乎有点复杂ated。如果您不抛出异常,则会选择
Runnable
。@Makoto引用的代码规则仅适用于显式类型的lambda。因此我建议他添加OP中的lambda被视为显式类型的原因。有趣的是,规范没有说R₁ 必须是非
void
,因此,如果两个函数类型都是
void
,我可以调用比另一个更具体的函数类型,这取决于哪个是
S
,哪个是
T
。“其中所有的返回语句都是无值的”,当它们都是无值时,这是一个无意义的语句。我还可以说“其中所有的返回语句都提供了一个值”。这并不能证明任何事情。它也没有被归类为“始终返回值”,但与值兼容,正如字面上所说,这意味着它与声明为返回值的函数兼容,而不是它确实返回值。@Holger
如果块中的每个返回语句都有return形式,则块lambda body是void兼容的;
别怪我,这是定义。acc根据该定义,其中不包含
返回值的内容被视为无效兼容。@Holger和for value compatible:
块lambda体如果不能正常完成,则其值兼容(§14.21)块中的每个return语句都有格式return Expression;
同样,总是引发异常的内容将被归类为值兼容,因为块中的每个return语句都有格式
return Expression;
(并且它也不能正常完成)但是由于某种未知的原因,当涉及到与值兼容的lambda表达式时,您忽略了相同的定义。在这里,您没有写“其中的所有返回语句都提供一个值”这句话。这样写仍然是荒谬的,特别是当您没有引用正式定义时(希望你的读者知道这一点,这会使你的解释变得过时)。写下没有矛盾的
return
语句会更有意义。然后大家都应该清楚,那就是