Java 如果实际参数是lambda,则在重载方法之间进行选择
在Java 1.8中,以下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不共享任何公共层次结构,并且大多数特定的类型规则在此不适用,编译器如何在重载方法之间进行选择
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
语句会更有意义。然后大家都应该清楚,那就是