函数式接口的核心定义是有且仅有一个抽象方法的接口,专为lambda表达式和方法引用设计;其判定只看本质:仅1个未实现抽象方法,default、static及object方法不计入,@functionalinterface为推荐非强制注解。

函数式接口的核心就一句话:有且仅有一个抽象方法的接口,专为 Lambda 表达式和方法引用而生。
关键判定规则
判断一个接口是不是函数式接口,不看注解,只看本质:
- 接口中必须且只能有 1 个未实现的抽象方法(public abstract)
- 默认方法(
default)、静态方法(static)可任意多个,不影响函数式特性 - 覆盖
Object类的方法(如toString()、equals()、hashCode())不算抽象方法,不破坏函数式契约 -
@FunctionalInterface是推荐标注,不是强制要求;但它能触发编译器检查——一旦多写或漏写抽象方法,立刻报错
四大基础接口要拎得清
Java 标准库把最常用逻辑抽象成四个“原子”接口,其他都是它们的变体或组合:
-
Predicate
:输入 T,输出boolean—— 用在filter、条件校验场景,比如s -> s.length() > 0 -
Function
:输入 T,输出R—— 用在map、类型转换,比如String::length或Integer::parseInt -
Consumer
:输入 T,无返回值(void)—— 用在副作用操作,比如打印、入库、发消息,System.out::println就是典型 -
Supplier
:无参数,输出 T—— 用在懒加载、工厂创建,比如LocalDate::now或() -> new ArrayList()
扩展与组合才是实战重点
光记基础不够,实际编码中常遇到这些情况:
- 双参数?用
BiFunction<t></t>、BiPredicate<t></t>、BiConsumer<t></t>—— 比如Map.forEach((k,v) -> System.out.println(k + "=" + v)) - 基本类型性能敏感?避开装箱,直接用
IntConsumer、LongSupplier、DoublePredicate等特化接口 - 想链式处理?善用组合方法:
Function.andThen()顺序执行,Predicate.and()合并条件,Consumer.andThen()串起多个动作 - 自定义也很简单:只要满足单抽象方法约束,加个
@FunctionalInterface,就能当 Lambda 类型用,无需继承任何类
别掉进两个常见坑
新手容易混淆或忽略的点:
-
Comparator<t></t>是函数式接口,虽然源码里有compare()和equals(),但后者是Object方法,不算额外抽象方法 -
Runnable是最古老、最典型的函数式接口——它没有参数、没有返回值,对应的是() -> { ... }这种零参无返 Lambda - 不要以为只有
java.util.function里的才算——java.lang.Runnable、java.awt.event.ActionListener都是合法函数式接口 - Lambda 能写的,匿名内部类也能写;但反过来,匿名内部类能干的(比如带状态),Lambda 不一定方便——函数式接口强调“无状态”和“可组合”,不是万能替代品
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











