MST
星途 面试题库

面试题:Java CompletableFuture链式调用中异常处理的优化策略

在复杂的CompletableFuture链式调用场景下,如何优化异常处理以提高代码的可读性、可维护性和性能?请结合具体案例,说明在链式调用的不同环节(如不同阶段的任务执行、结果转换等)如何合理地使用异常处理机制,同时避免异常处理代码的冗余和混乱。
13.3万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

1. 统一异常处理

在链式调用的末尾使用exceptionally方法来捕获整个链条中的异常,这样可以避免在每个阶段都重复写异常处理代码,提高代码可读性和可维护性。

CompletableFuture.supplyAsync(() -> {
    // 模拟可能抛出异常的任务
    if (Math.random() > 0.5) {
        throw new RuntimeException("任务1异常");
    }
    return "任务1结果";
})
.thenApply(result -> {
    // 模拟结果转换
    return result + " 转换后";
})
.exceptionally(ex -> {
    // 统一处理异常
    System.err.println("捕获到异常: " + ex.getMessage());
    return "默认值";
})
.thenAccept(System.out::println);

2. 针对特定阶段处理异常

如果某些阶段的异常需要特殊处理,可以在该阶段使用handle方法。handle方法可以同时处理正常结果和异常情况。

CompletableFuture.supplyAsync(() -> {
    // 模拟可能抛出异常的任务
    if (Math.random() > 0.5) {
        throw new RuntimeException("任务1异常");
    }
    return "任务1结果";
})
.handle((result, ex) -> {
    if (ex != null) {
        // 处理任务1的异常
        System.err.println("任务1异常: " + ex.getMessage());
        return "任务1异常默认值";
    }
    return result;
})
.thenApply(result -> {
    // 模拟结果转换
    return result + " 转换后";
})
.thenAccept(System.out::println);

3. 使用自定义异常类

定义特定业务场景的异常类,这样在异常处理时可以更明确地知道异常类型,便于针对性处理。

class CustomBusinessException extends RuntimeException {
    public CustomBusinessException(String message) {
        super(message);
    }
}

CompletableFuture.supplyAsync(() -> {
    // 模拟可能抛出自定义异常的任务
    if (Math.random() > 0.5) {
        throw new CustomBusinessException("自定义业务异常");
    }
    return "任务1结果";
})
.exceptionally(ex -> {
    if (ex instanceof CustomBusinessException) {
        // 处理自定义业务异常
        System.err.println("自定义业务异常: " + ex.getMessage());
        return "自定义业务异常默认值";
    }
    return "其他异常默认值";
})
.thenAccept(System.out::println);

4. 避免异常处理代码冗余

避免在每个thenApplythenCompose等方法中都写类似的异常处理代码。尽可能将通用的异常处理逻辑放在exceptionallyhandle中,减少冗余。

通过以上几种方式,可以在复杂的CompletableFuture链式调用场景下,优化异常处理,提高代码的可读性、可维护性和性能。