Java中Function接口的compose和andThen实现函数组合:compose先执行参数函数再执行当前函数,andThen则相反;二者均支持链式调用,提升代码清晰度与复用性。

Java 中 Function 接口的 compose 和 andThen 是实现函数组合的核心方法,它们让多个函数像流水线一样串起来执行,无需手动嵌套调用,代码更清晰、复用性更高。
compose:先执行参数函数,再执行当前函数
compose 的签名是:<V> Function<V, R> compose(Function<V, T> before)。它表示“先做 before,再做当前函数”。输入类型是 V,输出类型是当前函数的返回类型 R。
比如:
Function<String, Integer> strToInt = s -> Integer.parseInt(s);
Function<Integer, String> intToHex = i -> String.format("0x%x", i);
// 先转整数,再转十六进制字符串
Function<String, String> strToHex = intToHex.compose(strToInt);
System.out.println(strToHex.apply("255")); // 输出 "0x ff"
等价于:intToHex.apply(strToInt.apply("255"))。
立即学习“Java免费学习笔记(深入)”;
常见用法:
- 前置预处理:如字符串 trim → parse → validate,可把 trim + parse 封装为一个
compose链 - 解耦校验逻辑:把“非空校验”作为独立
Function,用compose插入到业务函数前 - 注意:
compose的参数函数必须返回类型匹配当前函数的输入类型
andThen:先执行当前函数,再执行参数函数
andThen 的签名是:<V> Function<T, V> andThen(Function<R, V> after)。它表示“先做当前函数,再做 after”。输入类型仍是 T,输出变成 after 的返回类型 V。
同样例子:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
Function<String, Integer> strToInt = s -> Integer.parseInt(s);
Function<Integer, Double> intToDouble = i -> i * 1.5;
// 先转整数,再乘以 1.5
Function<String, Double> strToDouble = strToInt.andThen(intToDouble);
System.out.println(strToDouble.apply("10")); // 输出 15.0
等价于:intToDouble.apply(strToInt.apply("10"))。
典型场景:
- 后置转换:如数据库查出对象 → 转 DTO → 转 JSON 字符串,用
andThen逐层包装 - 日志或监控埋点:在核心逻辑后接一个记录耗时的
Function - 异常统一包装:主函数返回结果后,用
andThen包一层Response.ok()
组合多个函数:链式调用很自然
compose 和 andThen 返回的仍是 Function,所以支持连续调用。例如:
Function<String, String> clean = s -> s.trim().toLowerCase();
Function<String, Integer> len = s -> s.length();
Function<Integer, Boolean> isLong = i -> i > 5;
Function<String, Boolean> check = clean.andThen(len).andThen(isLong);
System.out.println(check.apply(" Hello ")); // true(trim 后是 "hello",长度 5 → false?等等,是 5 不大于 5 → false)
// 改成 > 4 就对了:isLong = i -> i > 4 → true
也可以混用:f.andThen(g).compose(h) 相当于 g(f(h(x))),读的时候从右往左理解执行顺序。
小技巧:
- 用变量命名体现组合意图,如
parseAndValidate、toDtoAndSerialize - 避免过长链:超过 4–5 层建议拆分成中间函数,提升可读性和可测性
- 组合时注意泛型兼容性,IDE 通常能及时提示类型不匹配
和方法引用配合更简洁
实际开发中,常把静态方法或实例方法直接作为函数使用,组合起来非常干净:
Function<String, String> upper = String::toUpperCase;
Function<String, Integer> length = String::length;
Function<String, Integer> upperLen = upper.andThen(length);
System.out.println(upperLen.apply("abc")); // 3
甚至可以组合构造器:
Function<String, Integer> toInt = Integer::new; // String → Integer(需 String 是数字格式) Function<Integer, String> toHex = i -> "0x" + Integer.toHexString(i); Function<String, String> strToHexViaCtor = toInt.andThen(toHex);
注意:方法引用要确保参数个数、类型、抛出异常都与 Function 签名一致;否则编译失败。

















