函数式接口必须作为方法参数类型明确声明,以承载行为契约;应自定义语义化接口而非硬套内置类型,泛型需确保可推断,禁止用Lambda或具体类替代接口类型。

函数式接口在方法签名中规范定义,核心是让参数类型明确指向一个“行为契约”,而非具体实现。它不是写在方法体里,而是作为方法的形参类型出现——这个类型本身必须是合法的函数式接口。
方法参数类型必须是函数式接口
只有当方法声明中某个参数的类型是函数式接口时,调用方才能传入 Lambda、方法引用或匿名内部类。例如:
- 正确:void process(List<String> list, Predicate<String> filter) —— Predicate 是标准函数式接口,test() 方法定义了“怎么判断”
- 错误:void process(List<String> list, Object condition) —— Object 无法承载行为语义,编译期无法校验 Lambda 是否匹配
接口定义要与使用场景语义对齐
不要硬套内置接口,当业务逻辑有明确含义时,应自定义带语义的函数式接口,并在方法签名中直接使用它:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 比如重试策略,用 RetryPolicy<Exception> 比用 Function<Integer, Boolean> 更清晰
- 方法签名示例:void executeWithRetry(Runnable task, RetryPolicy<Exception> policy)
- 调用时可写:executeWithRetry(() -> api.call(), (a, r, e) -> e instanceof TimeoutException)
泛型参数需约束合理,避免类型推断失败
方法签名中若含泛型函数式接口,注意类型变量要能被上下文推导出来:
立即学习“Java免费学习笔记(深入)”;
- 推荐写法:<T> List<T> transform(List<T> src, Function<T, T> mapper) —— T 可从 src 推出,mapper 的类型自然确定
- 不推荐写法:<T, R> List<R> transform(List<T> src, Function<T, R> mapper) —— 若调用时不显式指定 R,Lambda 中可能报错“无法推断函数返回类型”
避免在方法签名中混用抽象与具体实现类型
函数式接口是契约,不是工具类。方法签名中不应出现具体实现类(如 Lambda 表达式本身、匿名类实例),也不该用非函数式接口类型替代:
- 禁止:void handle(String s, () -> s.length() > 0) {...} —— Lambda 不是类型,不能作参数类型
- 禁止:void handle(String s, MyHelper helper) {...} —— 即使 helper 内部有 doCheck() 方法,也不等于它是函数式接口
- 正确路径:先定义 @FunctionalInterface MyPredicate,再写 void handle(String s, MyPredicate p)

















