thenApply 是 CompletableFuture 的同步转换方法,仅在前序任务成功完成时执行函数处理并返回新 CompletableFuture,不处理异常、不开启新线程,执行线程与前序任务相同。

thenApply 是 CompletableFuture 提供的同步转换方法,用于在前一个异步任务**成功完成**后,对其结果进行函数式处理,并返回一个新的 CompletableFuture。
核心特点:只在前序任务成功时执行,且在同一个线程(或调用线程)中运行
它不会开启新线程,也不处理异常——如果前序任务抛出异常,thenApply 中的函数**根本不会执行**,后续链式调用会直接继承该异常。
- 输入:一个
Function<t r></t>,接收上一步的结果T,返回转换后的新值R - 输出:新的
CompletableFuture<r></r>,其结果是函数计算后的值 - 执行时机:前序
CompletableFuture正常完成(即complete()或正常返回)后立即同步执行
基本用法示例:字符串转大写 + 长度计算
假设你已有一个异步获取用户名的任务:
CompletableFuture<String> nameFuture = CompletableFuture.supplyAsync(() -> {
try { Thread.sleep(100); } catch (InterruptedException e) {}
return "alice";
});
用 thenApply 转换结果:
立即学习“Java免费学习笔记(深入)”;
CompletableFuture<Integer> lengthFuture = nameFuture.thenApply(name -> {
System.out.println("当前线程: " + Thread.currentThread().getName()); // 通常和 supplyAsync 的线程相同
return name.toUpperCase().length();
});
最终 lengthFuture 会完成为 5("ALICE".length())。
注意:不能处理异常,需搭配 exceptionally 或 handle
如果上游任务失败(比如抛出 RuntimeException),thenApply 的 lambda 不会触发。此时应使用:
-
exceptionally(Function<throwable t> fallback)</throwable>:仅处理异常,返回默认值 -
handle(BiFunction<t throwable r> handler)</t>:统一处理成功/失败两种情况
例如安全地转大写(避免 null):
CompletableFuture<String> safeUpper = nameFuture.handle((name, ex) -> {
if (ex != null) return "UNKNOWN";
return name != null ? name.toUpperCase() : "EMPTY";
});
与 thenCompose、thenAccept 的关键区别
-
thenApply:返回值 → 新的CompletableFuture(适合“变换”) -
thenCompose:返回值本身是CompletableFuture→ 扁平化嵌套(适合“接力异步任务”) -
thenAccept:无返回值(Consumer)→ 适合日志、存储等副作用操作
选错可能导致类型不匹配或意外阻塞。比如想把字符串查库再返回 ID,应该用 thenCompose,而不是 thenApply 返回 CompletableFuture<Long>


















