自定义函数式接口旨在抽取业务中可变逻辑,使主流程聚焦“做什么”;须满足:interface声明、仅一个未重写的公共抽象方法、可含default/static及Object方法;加@FunctionalInterface注解可确保编译期校验抽象方法数量。

自定义函数式接口不是为了“多写一个接口”,而是把业务中可变的逻辑抽出来,让主流程只关心“做什么”,不纠缠“怎么做”。关键在明确意图、控制抽象粒度、守住函数式契约。
必须满足的硬性条件
一个接口要成为合法的函数式接口,得同时满足三点:
- 必须用 interface 声明,不能是类或抽象类
- 有且仅有一个未被重写的公共抽象方法(比如
boolean check(User user)) - 可以自由添加任意 default 方法、static 方法,以及从
Object继承的equals、toString等——它们都不算抽象方法
加 @FunctionalInterface 注解才真正靠谱
这个注解不是装饰,是编译期守门员:
- 加了它,编译器会强制检查:抽象方法是不是恰好 1 个?多了或少了直接报错
- 不加它,只要结构符合,仍能用 Lambda;但后续有人误加一个抽象方法,编译不会拦,运行时才暴露问题
- 它和
@Override类似,属于语义增强型注解,不改行为,只保安全
方法命名和参数设计要贴业务
别写 apply、doIt 这类泛化名字,直接体现动作和上下文:
- ✅ 推荐:
boolean isEligibleForPromotion(Order order)—— 动词开头,参数是领域对象,一眼懂意图 - ❌ 避免:
Object execute(Object input)—— 类型模糊,失去编译检查,也难维护 - 多个输入时,优先封装成单个领域对象(如
RiskContext),而不是堆(String, Long, Date, boolean)
泛型 + 领域类型提升复用性和安全性
当逻辑适用于不同实体时,用泛型固化边界:
- 定义:
@FunctionalInterface interface Validator{ boolean validate(T target); } - 使用:
ValidatororderValidator = o -> o.getAmount().compareTo(BigDecimal.ZERO) > 0; - 效果:编译器禁止你把
User传给orderValidator.validate(),错误提前暴露
实现方式按复杂度选
具体怎么实现,看逻辑轻重:
- 简单判断或转换 → 直接用 Lambda:
isExpired = d -> d.before(new Date()) - 已有静态/实例方法 → 用方法引用:
String::toLowerCase或validator::validate - 逻辑较重或需复用 → 单独写实现类,但注意别破坏“只做一件事”的原则
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











