编译器如何知道在 ExecutorService 中提交(Callable<T> 任务)或提交(Runnable 任务)时使用哪个 lambda?

How compiler knows which lambda to use in submit(Callable<T> task) or submit(Runnable task) in ExecutorService?

submit() method accepts both Runnable and callable as parameters. but it returns Future when we send callable interface as a parameter.

所以当 lambda 发布时

() -> {}

编译器如何知道要使用哪个功能接口?可调用还是可运行? AFAIK 编译器不够聪明,无法分析表达式 return 是否存在,或者我错了吗?

对于任何 T,lambda 表达式 () -> {}Callable<T> 不兼容,而它 Runnable 兼容.因此选择 Runnable 重载。

JLS 的 15.27.3 and 15.27.2 部分解释了为什么会这样。

A lambda expression is compatible in an [...] invocation context [...] with a target type T if T is a functional interface type (§9.8) and the expression is congruent with the function type of the ground target type derived from T.

这里Callable<T>的地面目标类型还是Callable<T>。让我们看看“一致”是什么意思:

A lambda expression is congruent with a function type if all of the following are true:

[...]

  • If the function type's result is a (non-void) type R, then either i) the lambda body is an expression that is compatible with R in an assignment context, or ii) the lambda body is a value-compatible block, and each result expression (§15.27.2) is compatible with R in an assignment context.

“值兼容块”定义为:

A block lambda body is value-compatible if it cannot complete normally (§14.21) and every return statement in the block has the form return Expression;.

还有:

In a value-compatible block lambda body, the result expressions are any expressions that may produce an invocation's value. Specifically, for each statement of the form return Expression ; contained by the body, the Expression is a result expression.

因此,“编译器不够智能,无法分析表达式 return 是否存在”的说法是错误的。任何 Java 编译器都需要遵循规范所说的内容,并分析块是否正常完成(大致意味着完成 运行 而没有到达 returnthrow 语句)。

() -> {}的情况下。没有 return 语句,因此块总是正常完成。