lambda赋值成功即为函数式接口;编译失败提示抽象方法超限时说明不合规;@functionalinterface注解可提前拦截多抽象方法错误。

直接用 Lambda 表达式去“试写”,是最直观、最可靠的验证方式。只要能成功赋值,就说明该接口满足单抽象方法(SAM)要求;一旦编译报错,红线就被触碰了。
用 Lambda 赋值来检验
把接口类型作为变量声明,右侧用最简 Lambda 实现其抽象方法:
- 如果编译通过,且 IDE 不报红、运行正常 → 接口是函数式接口
- 如果编译失败,提示类似 "Incompatible functional interface: X abstract methods" 或 "Not a functional interface" → 接口含多个抽象方法,不合规
- 注意:即使没加
@FunctionalInterface注解,只要能写 Lambda,它就是隐式的函数式接口
重点看抽象方法数量,不是总方法数
接口里可以有 default 方法、static 方法、甚至继承自 Object 的 public 方法(如 toString()、hashCode()),这些都不算抽象方法:
-
default void log() { }→ 允许存在,不影响 SAM 判定 -
static String name() { return "A"; }→ 允许存在 -
boolean equals(Object o);→ 是 Object 原生方法,不算新增抽象方法 - 真正只数那些未实现、非 static、非 default、非 Object 继承而来的 public/protected/包级方法
快速反例检测法
故意在接口里多加一个抽象方法,再尝试写 Lambda:
- 原接口:
interface Task { void run(); }→Task t = () -> System.out.println("ok");✅ 成功 - 加一个:
interface Task { void run(); String desc(); }→ 同样赋值语句 ❌ 编译失败 - 失败信息会明确指出“Task is not a functional interface”,这就是红线被踩中的信号
配合 @FunctionalInterface 注解双重保险
在接口上加上 @FunctionalInterface,编译器会在你无意中添加第二个抽象方法时立刻报错:
- 加注解后,哪怕只是多写了一个
void init();,保存即报错 - 这个注解不改变行为,只起编译期校验作用,推荐所有自定义函数式接口都加上
- 它不是必需的,但它是防止越界最省力的防线










