函数式接口是Java 8引入的、有且仅有一个抽象方法的接口;核心特征包括:抽象方法唯一(不计Object继承方法、default方法和static方法),推荐使用@FunctionalInterface注解以启用编译期校验,是Lambda表达式和方法引用的唯一合法目标类型。

函数式接口是 Java 8 引入函数式编程的关键基础,面试中常被用来考察对 Lambda 表达式、接口设计和类型系统本质的理解。回答时需紧扣“单一抽象方法”这一核心,避免泛泛而谈。
什么是函数式接口?关键特征有哪些?
函数式接口是指有且仅有一个抽象方法的接口。这个“仅一个”指用户定义的抽象方法数量,不包括:
- 从 Object 继承的方法(如 toString、equals、hashCode)
- default 方法(可有多个)
- static 方法(可有多个)
@FunctionalInterface 是编译期检查注解,不是必需但强烈推荐——加了它,若误增第二个抽象方法,编译器立刻报错,提升代码健壮性。
Java 标准库中哪些是典型函数式接口?怎么用?
主要在 java.util.function 包中,常见四个必须掌握:
立即学习“Java免费学习笔记(深入)”;
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
-
Predicate
:输入 T,返回 boolean;适合条件判断。例: Predicate<string> isEmpty = s -> s == null || s.trim().isEmpty();</string> -
Function
:输入 T,输出 R;用于数据转换。例: Function<integer string> intToStr = i -> "num_" + i;</integer> -
Consumer
:输入 T,无返回值;适合消费/处理动作。例: Consumer<string> printer = System.out::println;</string> -
Supplier
:无输入,返回 T;适合惰性创建对象。例: Supplier<localdatetime> now = LocalDateTime::now;</localdatetime>
Lambda 表达式与函数式接口的关系是什么?
Lambda 表达式只能用于目标类型为函数式接口的上下文。它本质上是该接口的匿名实现,编译后会生成一个实现了该接口的类实例。
使用前提有两个缺一不可:
- 接口必须是函数式接口(否则编译失败)
- 变量声明或方法参数类型必须明确是该函数式接口(让编译器能推导出目标类型)
比如 list.forEach(s -> System.out.println(s)) 中,forEach 参数类型是 Consumer
如何自定义函数式接口?要注意什么?
自定义时只需确保只有一个抽象方法,并建议加上 @FunctionalInterface 注解:
public interface TriFunctionR apply(T t, U u, V v);
}
注意点:
- 不要在接口里加第二个抽象方法,否则失去函数式特性
- 可以放心添加 default 方法(如组合逻辑)或 static 工厂方法(如 and()、or())
- 如果已有老接口(如 Runnable、Comparator),它们天然符合函数式接口定义,可直接用于 Lambda

















