讨论/《Java 实战(第 2 版)》 - 3.5.2 同样的 Lambda,不同的函数式接口/
《Java 实战(第 2 版)》 - 3.5.2 同样的 Lambda,不同的函数式接口
共 1 个回复

答案:Lambda表达式的上下文是Object(目标类型)。但Object不是一个函数式接口。为了解决这个问题,你可以把目标类型改成Runnable,它的函数描述符是() -> void

Runnable r = () -> { System.out.println("Tricky example"); };

你还可以通过强制类型转换将Lambda表达式转换成Runnable,显式地生成一个目标类型,以这种方式来修复这个问题:

Object o = (Runnable) () -> { System.out.println("Tricky example"); };

处理方法重载时,如果两个不同的函数式接口却有着同样的函数描述符,使用这个技巧有立竿见影的效果。到底该选择使用哪一个方法签名呢?为了消除这种显式的二义性,你可以对Lamda进行强制类型转换。

譬如,下面这段代码中,方法调用execute( () -> {} )使用了execute方法,不过它存在着二义性,因为RunnableAction接口中都提供了同样的函数描述符:

public void execute(Runnable runnable) {
runnable.run();
}
public void execute(Action<T> action) {
action.act();
}
@FunctionalInterface
interface Action {
void act();
}

然而,通过强制类型转换表达式,这种显式的二义性被消除了:

execute((Action) () -> { });