web-dev-qa-db-ja.com

機能Java-whenCompleteと例外の相互作用

このコードでは:

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

doSomethingThatMightThrowAnExceptionからの例外がある場合、doSomethingElsehandleExceptionの両方が実行されますか、それともwhenCompleteまたはexceptionallyのどちらかが例外を消費しますか?

編集:

doSomethingThatMightThrowAnExceptionは、CompletableFutureを返す可能性があるcompleteExceptionallyを返します。これは私が話している例外です。

18
peco

whenComplete の[/ documentation]には次のように書かれています:

このステージが完了すると、指定されたアクションを実行する新しいCompletionStage このステージと同じ結果または例外を持つを返します。

(強調鉱山)

これは、同じ結果または例外を持つことになっているため、このステージで例外が飲み込まれないことを意味します。ただし、 here で説明されているように、後続のステージが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

連鎖するのではなく、常に1つのステージに複数のアクションを追加できることに注意してください。

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

もちろん、現在、ステージ間に依存関係はありません2aおよび2b、それらの間には順序がなく、非同期アクションの場合、それらは同時に実行される可能性があります。

22
Holger

例外的に メソッドの状態:

このCompletableFutureが完了したときに完了する新しいCompletableFutureを返します。例外の指定された関数の結果が、例外的に完了したときにこのCompletableFutureの完了をトリガーします。それ以外の場合、このCompletableFutureが正常に完了すると、返されたCompletableFutureも同じ値で正常に完了します。注:whenCompleteおよびhandleメソッドを使用すると、この機能のより柔軟なバージョンを利用できます。

これはそうではありません。私見は最も明確な英語で書かれていますが、例外がスローされた場合、exceptionallyアクションのみがトリガーされることを意味します。例外がスローされない場合、normalアクションのみが実行されます。

3
OldCurmudgeon

doSomethingThatMightThrowAnException().whenComplete((result, ex) -> doSomethingElse()})および.exceptionally(ex -> handleException(ex));とチェーンされますが、例外がスローされると、チェーン内にオブジェクトが渡されないため、例外はすぐに終了します。

例外は呼び出し元にスローされるので、doSomethingThatMightThrowAnException()が内部で例外をキャッチしない限りスローされます。これがあなたのクラスである場合、それがスローするかどうかを知る必要があります。そうでない場合は、使用しているライブラリのドキュメントを確認してください。

0
Tuxxy_Thang