函数式Java - whenComplete和exception之间的交互



在此代码中:

doSomethingThatMightThrowAnException()
  .whenComplete((result, ex) -> doSomethingElse()})
  .exceptionally(ex -> handleException(ex));

doSomethingThatMightThrowAnException出现异常时,是doSomethingElsehandleException同时运行,还是该异常被whenCompleteexceptionally消耗?

编辑:

doSomethingThatMightThrowAnException返回一个CompletableFuture,它可能是completeExceptionally。这就是我所说的例外

whenComplete的文档说:

返回一个新的CompletionStage ,其结果或异常与此阶段相同,该阶段在此阶段完成时执行给定的操作。

<一口>(强调我的)

这意味着异常不会被这个阶段吞没,因为它应该具有相同的结果或异常。然而,您可能会对以下事实感到惊讶,即后续阶段将接收到包装在CompletionException中的前一个阶段的异常,正如这里所讨论的那样,因此它不是完全相同的异常:

CompletableFuture<String> test=new CompletableFuture<>();
test.whenComplete((result, ex) -> System.out.println("stage 2: "+result+"t"+ex))
    .exceptionally(ex -> { System.out.println("stage 3: "+ex); return ""; });
test.completeExceptionally(new IOException());

将打印:

stage 2: null   java.io.IOException
stage 3: java.util.concurrent.CompletionException: java.io.IOException

注意,你总是可以在一个舞台上附加多个动作,而不是将它们链接起来:

CompletableFuture<String> test=new CompletableFuture<>();
test.whenComplete((result, ex) -> System.out.println("stage 2a: "+result+"t"+ex));
test.exceptionally(ex -> { System.out.println("stage 2b: "+ex); return ""; });
test.completeExceptionally(new IOException());
stage 2b: java.io.IOException
stage 2a: null  java.io.IOException

当然,由于2a2b阶段之间没有依赖关系,因此它们之间没有排序,并且在异步操作的情况下,它们可以并发运行

异常方法声明:

返回一个新的CompletableFuture,当这个CompletableFuture完成时,这个CompletableFuture被完成,当它异常完成时,异常函数的结果触发这个CompletableFuture的完成;否则,如果这个CompletableFuture正常完成,那么返回的CompletableFuture也会以相同的值正常完成。注意:此功能的更灵活的版本可以使用方法whenComplete和handle。

这不是用最清晰的英语写的,但我想说的是,这意味着如果抛出异常,那么只有exceptionally动作将被触发。如果没有抛出异常,则只执行normal动作。

doSomethingThatMightThrowAnException().whenComplete((result, ex) -> doSomethingElse()}).exceptionally(ex -> handleException(ex));链接在一起,但是如果它抛出异常,它将在那里结束,因为没有对象将在链中传递。

请记住异常会抛出给调用者,所以除非doSomethingThatMightThrowAnException()在内部捕获异常,否则它将抛出。如果这是你的类,你应该知道它是否抛出,如果没有检查你使用的库的文档

最新更新