Consumer.andThen() 返回新Consumer,执行顺序为从左到右:先本体后参数,等价于依次调用;不支持中断、条件跳过或异常恢复,需手动处理受检异常与线程安全。

Consumer.andThen() 本身不返回新 Consumer,而是返回一个执行完当前动作后再执行参数动作的 Consumer;直接链式调用 andThen() 多次是可行的,但必须注意执行顺序和副作用累积。
andThen() 的执行顺序是“先左后右”
很多人误以为 consumer1.andThen(consumer2).andThen(consumer3) 是从右往左执行,实际是:先执行 consumer1,再执行 consumer2,最后执行 consumer3。这和函数组合(如 Function.compose())相反。
-
andThen()内部逻辑是:return (t) -> { this.accept(t); after.accept(t); },即“本体先跑,参数后跑” - 连续调用时,
a.andThen(b).andThen(c)等价于(t) -> { a.accept(t); b.accept(t); c.accept(t); } - 如果某个
Consumer修改了入参对象状态(比如 set 字段),后续Consumer拿到的是已被修改的对象
不能用于需要中断或条件跳过的场景
Consumer 接口没有返回值,andThen() 也无法感知前序动作是否抛异常或应跳过后续步骤——它只负责“硬性串联”。一旦中间抛出 RuntimeException,整个链就断了,且无内置恢复机制。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 若需条件执行(如“仅当用户已激活才发邮件”),得在每个
Consumer内部手动判断,不能靠andThen()自动跳过 - 若某步可能抛
IOException等受检异常,必须包装成运行时异常(如RuntimeException),否则编译不通过 - 常见错误写法:
list.forEach(System.out::println.andThen(s -> Files.write(...)))—— 这里Files.write()抛IOException,必须显式捕获并转为运行时异常
和 Stream.peek() / forEach() 混用时容易误判执行时机
在 Stream 中用 andThen() 组合多个 Consumer,常被当成“流内多阶段处理”,但要注意:它不会改变流元素,也不参与短路操作;且若流是惰性的(如未终端操作),andThen() 根本不会触发。
-
stream.peek(a.andThen(b))和stream.peek(a).peek(b)行为一致,但前者更易封装复用 - 若混用
forEach()和andThen(),比如list.parallelStream().forEach(c1.andThen(c2)),要确保c1和c2是线程安全的(比如不共享可变状态) - 不要指望
andThen()能替代map()或filter():它不产生新值、不筛选元素、不支持中断
真正关键的一点是:andThen() 只是语法糖,背后没有魔法。它的所有行为都取决于你传进去的 Consumer 是否有状态、是否线程安全、是否抛异常——这些责任全在使用者手上,接口本身不约束也不提醒。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










