宝塔服务器面板,一键全能部署及管理,送你10850元礼包,点我领取

使用 CompletableFuture 编写代码时,异常处理很重要。
CompletableFuture 提供了三种方法来处理它们:handle()、whenComplete() 和 exceptionly()。

 
  handle() whenComplete() exceptionly()
访问成功 Yes Yes No
访问失败 Yes Yes Yes
能从失败中恢复 Yes No Yes
能转换结果从T 到 U Yes No No
成功时触发 Yes Yes No
失败时触发 Yes Yes Yes
有异步版本 Yes Yes Yes(12版本)

1、handle()

public <U> CompletableFuture<U> handle(java.util.function.BiFunction<? super T, Throwable, ? extends U> fn)

返回一个新的 CompletionStage阶段,当此阶段正常或异常完成时,将使用此阶段的结果和异常作为所提供函数的参数来执行。

当此阶段完成时,以该阶段的结果(如果没有则为null)和该阶段的异常(如果没有则为null)作为参数调用给定函数,并且函数的结果用于完成返回的阶段

不会把异常外抛出来。

    public static CompletableFuture divide(int a, int b){
        return CompletableFuture.supplyAsync(() -> a/b)
                .handle((result, ex) -> {
                    if (null != ex) {
                        System.out.println(ex.getMessage());
                        return 0;
                    } else {
                        return result;
                    }
                });
    }

        try {
            System.out.println("success:	"+divide(6,3).get());
            System.out.println("exception:	"+divide(6,0).get());
        } catch (Exception exception){
            System.out.println("catch="+exception.getMessage());
        }

输出结果:
success:    2
java.lang.ArithmeticException: / by zero
exception:    0
 

2、whenComplete()

public CompletableFuture<T> whenComplete(java.util.function.BiConsumer<? super T, ? super Throwable> action)

可以访问当前completable future的结果和异常作为参数:使用它们并执行您想要的操作。

此方法并不能转换完成的结果。会内部抛出异常。

    public static CompletableFuture whenComplete(int a, int b){
        return CompletableFuture.supplyAsync(() -> a/b)
                .whenComplete((result, ex) -> {
                    if (null != ex) {
                        System.out.println("whenComplete error:	"+ex.getMessage());
                    }
                });
    }

        try {
            System.out.println("success:	"+whenComplete(6,3).get());
            System.out.println("exception:	"+whenComplete(6,0).get());
        } catch (Exception exception){
            System.out.println("catch===="+exception.getMessage());
        }

输出:

success:    2
whenComplete error:    java.lang.ArithmeticException: / by zero
catch====java.lang.ArithmeticException: / by zero

3、exceptionly()


public CompletableFuture<T> exceptionally(java.util.function.Function<Throwable, ? extends T> fn)

该方法仅处理异常情况:发生异常时。
如果可完成的未来成功完成,那么“异常”内部的逻辑将被跳过。

不会把内部异常抛出来。


    public static CompletableFuture exceptionally(int a, int b){
        return CompletableFuture.supplyAsync(() -> a/b)
                .exceptionally(ex -> {
                    System.out.println("ex:	"+ex.getMessage());
                    return 0;
                });
    }

        try {
System.out.println("success:	"+FutureTest.exceptionally(6,3).get());
            System.out.println("exception:	"+FutureTest.exceptionally(6,0).get());
        } catch (Exception exception){
            System.out.println("catch===="+exception.getMessage());
        }


输出:
success:    2
ex:    java.lang.ArithmeticException: / by zero
exception:    0

如果只专注于异常处理,选择exceptionally(),它可以简化了输入参数,并且可以避免异常空检查的if语句。

如果希望不影响主流程,也不加try进行捕获,使用handle()方法,它可以从异常中恢复过来。