泛型接口可成为函数式接口,前提是仅含一个抽象方法;此时可用Lambda赋值或传参,编译器依目标类型推断泛型参数,需满足参数、返回值及异常声明的匹配要求。

泛型接口可以成为函数式接口,前提是它只含一个抽象方法;只要满足这个条件,就能直接用 Lambda 表达式赋值或传参,编译器会根据上下文自动推断类型。
泛型接口要成为函数式接口的关键条件
函数式接口的本质是“单抽象方法”(SAM),泛型不改变这一规则。泛型只是让接口更通用,不影响其函数式身份的判定。
- 必须仅有一个未被重写的抽象方法(默认方法、静态方法、Object 的 public 方法不计)
- 推荐加 @FunctionalInterface 注解,便于编译器检查和文档说明
- 泛型参数可出现在方法签名的任意位置:参数类型、返回类型、异常声明中
Lambda 如何匹配泛型函数式接口
编译器通过目标类型(target type)推断 Lambda 的语义。当把 Lambda 传给某个方法,而该方法形参是 MyFunc
- 参数数量、类型需与抽象方法一致(如
T getValue(T t)要求 Lambda 有且仅有一个同类型参数) - 返回值类型也需匹配(如方法声明返回
T,Lambda 主体末尾表达式结果必须是T或其子类型) - 若抽象方法声明了受检异常,Lambda 主体抛出的异常必须在该声明范围内
实际传参写法示例
假设定义了如下泛型函数式接口:
@FunctionalInterface
public interface Mapper<t r> {
R map(T input);
}</t>使用时可这样传递 Lambda:
-
直接赋值:
MapperintToStr = i -> "num:" + i; -
作为方法参数:
processData(list, item -> item.getName().toUpperCase());(前提是processData第二个参数类型是Mapper) -
结合类型推断:调用
stream().map(s -> s.length())时,编译器从 Stream和 map 方法签名自动推出 Lambda 类型为 Function
常见误区提醒
不是所有带泛型的接口都能接 Lambda;关键不在有没有泛型,而在是否“只有一项待实现的行为”。
- 错误:接口里写了两个抽象方法,哪怕都带泛型,也不能用 Lambda 直接实现
- 错误:把 Lambda 赋给原始类型变量(如
Mapper m = s -> s;),会丢失泛型信息,可能引发类型不安全或编译失败 - 注意:Lambda 捕获的局部变量必须是 effectively final,这条规则对泛型接口同样适用










