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

时间:2015-10-21 14:44:58

标签: java lambda functional-programming java-8

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

() -> {
    throw new RuntimeException("FIXME");
}

但是,如果我使用单参数方法将其提交给ExecutorService并忽略返回值(即没有可用的类型推断信息),则在编译时选择ExecutorService#submit(Callable),除非我明确地将我的lambda转换为Runnable

如果RunnableCallable不共享任何公共层次结构且最具体的类型规则没有',编译器如何在上述情况下在重载方法之间进行选择适用于此?

2 个答案:

答案 0 :(得分:7)

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

从JLS部分15.12.2.5中,选择具有最特定类型的重载,如果有一个明确最具体的那样。这就是它对大多数特定功能接口类型的说法:

  

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

     

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

     
      
  • R2无效......
  •   

TRunnableSCallableCallable更具体,因为其返回类型不为空,因此Callable为选择

方法重载解析非常复杂,所以可能有一点我错过了,但我认为这就是为什么它选择Callable

答案 1 :(得分:4)

虽然@thecoop的答案是正确的,但值得一提的是lambda机制的另一个方面。

带有块体的Lambda分为两类:void-compatible and value-compatible

问题中的lambda都是,因为它无法正常完成(由于无条件的异常抛出),并且那里的所有return语句都是无值的并且返回一个值,看得出来就像那里一样根本没有return声明。

然而,大多数lambdas都是其中之一。如果lambda只有void-compatible,则lambda只与Runnable兼容。

稍微违反直觉(但在逻辑上正确)的是,即使问题中的lambda永远不会返回一个值,它也会被归类为"总是在sa {{1}时返回一个值}"