功能Java - 当完成和特殊之间的交互

2022-09-01 14:25:38

在此代码中:

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

当 存在 来自 的异常时,是否同时运行,或者异常是否由 或 ?doSomethingThatMightThrowAnExceptiondoSomethingElsehandleExceptionwhenCompleteexceptionally

编辑:

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


答案 1

whenComplete的文档说:

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

(强调我的)

这意味着异常不会被此阶段吞噬,因为它应该具有相同的结果或异常。但是,您可能会惊讶地发现,后续阶段将收到包装在 中的上一阶段的异常,如此所述,因此它不是完全相同的异常: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


答案 2

例外方法指出:

返回一个新的ComppletableFuture,该属性在此ComppletableFuture完成时完成,其给定函数的异常结果在异常完成时触发此ComppletableFuture的完成;否则,如果此ComppletableFuture正常完成,则返回的ComppletableFuture也以相同的值正常完成。注意:此功能的更灵活的版本可以使用“完成和处理”的方法。

这不是,恕我直言,用最清晰的英语写的,但我想说这意味着如果抛出异常,那么只会触发操作。如果未引发异常,则仅执行该操作。exceptionallynormal