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

Bas*_*ass 12 java lambda functional-programming java-8

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

() -> {
    throw new RuntimeException("FIXME");
}
Run Code Online (Sandbox Code Playgroud)

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

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

the*_*oop 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无效......

Tis Runnable,Sis Callable,Callable更具体,因为它的返回类型不是void,因此Callable被选中

方法重载分辨率非常复杂,所以可能有一点我错过了,但我认为这就是它选择的原因 Callable

  • 有趣的是,规范并没有说R 1必须是非"空",所以如果两种函数类型都是"void",我可以调用比另一种更具体,取决于哪个是`S`,哪个是`T` ...... (2认同)