Function接口的andThen和compose用于函数组合,执行顺序相反:andThen是先执行当前函数再执行参数函数(A→B→C),compose则先执行参数函数再执行当前函数(B→A)。

Java 中 Function 接口的 andThen 和 compose 都用于函数组合,但执行顺序相反:前者是“先自己,再别人”,后者是“先别人,再自己”。理解它们的调用顺序和类型匹配,是正确组合的关键。
andThen:A → B → C(链式后置)
andThen 表示当前函数执行完后,把结果传给参数函数继续处理。签名是:
假设 f: T → R,g: R → V,那么 f.andThen(g) 构成新函数 T → V,等价于 g(f(t))。
- 适合“加工流水线”场景:比如字符串转小写 → 去空格 → 取长度
- 注意类型必须连贯:f 的返回类型必须与 g 的入参类型兼容(支持协变)
- 示例:
FunctiontoLower = s -> s.toLowerCase();
Functionlength = s -> s.length();
FunctionlowerThenLength = toLower.andThen(length);
System.out.println(lowerThenLength.apply("HELLO")); // 输出 5
compose:A → B → C(前置注入)
compose 表示先执行参数函数,再把结果交给当前函数处理。签名是:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
default若 f: T → R,h: V → T,则 f.compose(h) 得到 V → R,等价于 f(h(v))。
- 适合“预处理”逻辑:比如先解析 JSON 字符串为对象,再从中提取字段
- 类型要求:h 的返回类型需与 f 的入参类型兼容
- 示例:
FunctiontoString = i -> "num:" + i;
Functionround = d -> (int) Math.round(d);
FunctionroundThenToString = toString.compose(round);
System.out.println(roundThenToString.apply(3.7)); // 输出 "num:4"
andThen 和 compose 可以嵌套使用
两者可多次调用,形成更长的函数链,但要注意方向一致性:
-
f.andThen(g).andThen(h)等价于h(g(f(x))) -
f.compose(g).compose(h)等价于f(g(h(x))) - 混合使用要小心:例如
f.andThen(g).compose(h)表示先 h,再 f,再 g,即g(f(h(x))) - 推荐保持风格统一,避免嵌套过深;必要时用变量命名中间函数提升可读性
实际组合中的常见陷阱
函数组合看似简单,但容易因类型或空值出错:
- 类型擦除导致泛型不匹配:编译器可能无法推断中间类型,显式指定泛型或拆分步骤可缓解
-
null 输入未处理:组合后的函数仍会抛
NullPointerException,建议在基础函数中做判空,或用Optional封装 -
异常不能直接传播:
Function不允许抛受检异常,如需异常处理,可自定义函数接口或用 try-catch 包裹逻辑 - 性能开销极小但存在:每次组合都会创建新对象,高频调用场景下可缓存组合结果

















