exceptionally是CompletableFuture中专用于异常降级的回调,仅在上游以异常方式完成时执行,返回同类型默认值以阻止异常传播;它不处理取消或超时,也不拦截已被handle/whenComplete处理的异常。

在 CompletableFuture 中用 exceptionally 捕获并降级异常,核心是把它当作“失败兜底回调”:当上游异步任务抛出异常时,它会接收该异常并返回一个默认/降级结果,从而避免异常传播中断链式调用。
exceptionally 的作用和触发时机
exceptionally 只在前序阶段(比如 supplyAsync、thenApply 等)**以异常方式完成**(即抛出未捕获的异常)时被调用。它不会响应 cancel 或 timeout(除非显式抛出异常),也不会拦截已通过 handle 或 whenComplete 处理过的异常。
- 如果上游成功完成,
exceptionally不执行,直接走后续的thenApply等正常链路 - 如果上游抛出异常(如
RuntimeException、IOException),exceptionally被调用,参数为该异常对象 - 它的返回值会作为整个 CompletableFuture 的最终结果(类型需与前序阶段一致)
基本用法:提供降级值
最常见场景是返回默认值或空对象,避免调用方收到异常:
CompletableFuture<String> future = CompletableFuture
.supplyAsync(() -> {
if (Math.random() > 0.5) throw new RuntimeException("服务暂时不可用");
return "原始数据";
})
.exceptionally(ex -> {
System.err.println("捕获异常: " + ex.getMessage());
return "降级数据"; // 类型必须是 String,与 supplyAsync 返回值一致
});
这样无论是否出错,future.join() 总能得到一个 String,不会抛出异常。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
配合 thenApply 实现安全转换
注意:exceptionally 返回的是同类型值,若后续还需处理,可接 thenApply —— 此时它对成功结果和降级结果一视同仁:
- 上游成功 →
exceptionally跳过 →thenApply处理原始结果 - 上游失败 →
exceptionally返回降级值 →thenApply处理该降级值
例如统一加前缀:
CompletableFuture<String> result = CompletableFuture
.supplyAsync(() -> riskyFetch())
.exceptionally(ex -> "fallback")
.thenApply(s -> "[OK] " + s); // 对原始结果和降级结果都生效
与 handle 和 whenComplete 的区别
三者都用于响应完成状态,但职责不同:
-
exceptionally:仅响应异常完成,必须返回同类型值,专用于降级 -
handle:响应所有完成状态(成功/异常),接收结果和异常两个参数,可统一处理并返回新值 -
whenComplete:响应所有完成状态,但不改变结果(返回void),适合记录日志、清理资源
如果既要降级又要记录日志,推荐组合使用:exceptionally 做降级 + whenComplete 做通用收尾。

















