因为 Java 编译器是通过 Lambda 表达式所在上下文或场景的目标类型来确定 Lambda 表达式的类型。故,我们只有在 Java 编译器可以确定目标类型的场景下,才能使用 Lambda 表达式。这样的场景有:
变量声明赋值return 语句数组初始化器方法或构造函数参数Lambda 表达式体条件表达式,?:强制转换表达式(Cast expression)Java 编译器常使用两个语言特性来确定目标类型:
重载解析(overload resolution)类型参数推断(type argument inference)假设我们有两个函数接口,且有两个重载方法分别以这两个函数接口作为其参数进行调用。代码如下:
package com.wuxianjiezh.test; public class TargetTypeTest { public interface SayHello { void run(); } public interface SayNothing<V> { V run(); } public void invoke(SayHello sayHello) { System.out.print("Hello:"); sayHello.run(); } public <T> T invoke(SayNothing<T> sayNothing) { return sayNothing.run(); } public static void main(String[] args) { TargetTypeTest test = new TargetTypeTest(); test.invoke(() -> System.out.println("嗒嗒嗒")); // 调用 `invoke(SayHello)` test.invoke(() -> "我是返回结果"); // // 调用 `invoke(SayNothing)` } }如上代码所示,我们通过方法重载,创建了两个 invoke 方法,其中一个没有返回值(invoke(SayHello)),另一个有返回值(invoke(SayNothing))。
因为 () -> System.out.println("嗒嗒嗒") 没有返回值,所以以其作为参数的 invoke 方法调用了 invoke(SayHello)。
而 () -> "我是返回结果" 存在返回值,所以以其作为参数的 invoke 方法调用了 invoke(SayNothing)。
以上代码的运行结果为:
Hello:嗒嗒嗒