web-dev-qa-db-ja.com

CompletionStageは常に例外をCompletionExceptionでラップしますか?

CompletionStage Javadocは次のように述べています。

[...]ステージの計算が(チェックされていない)例外またはエラーで突然終了した場合、完了を必要とするすべての依存ステージも例外的に完了し、CompletionExceptionが例外を原因として保持します。

例外補完は常にCompletionExceptionで例外をラップするものと見なされる理由exceptionally()whenComplete()handle()は例外をThrowableとして表す/ CompletionException

これは、これらのメソッド内で例外を直接再スローするのを防ぐため、重要です。

これらのメソッドがCompletionException以外の例外を受け取ることは可能ですか?または、このタイプにキャストを安全に強制できますか?

(私はいくつかのテストをローカルで実行しただけでなく、CompletableFutureソースコードを使ってDigしましたが、一見したところ、他の種類の例外がスローされる方法がわかりません。)

16
Gili

これらのメソッドがCompletionException以外の例外を受け取ることはありますか?

はい、可能です。CompletionExceptionチェック(または使用方法のレビュー)なしでinstanceofにキャストしないでください。

この例を取る

CompletableFuture<Void> root = new CompletableFuture<>();
root.whenComplete((v, t) -> {
    System.out.println(t.getClass()); // class Java.io.IOException
});
root.completeExceptionally(new IOException("blow it up"));

whenCompleteは、IOExceptionをラップするのではなく、CompletionExceptionを受け取ります。同じ動作がexceptionallyhandleにも当てはまります。


ステージの計算は、Javadocで定義されています。

ステージによって実行される計算は、FunctionConsumer、またはRunnableとして表すことができます(それぞれ、apply、accept、runなどの名前のメソッドを使用)。引数を必要とするか、結果を生成します。

私はこの見積もりを信じています

ステージの計算が(チェックされていない)例外またはエラーで突然終了した場合

それらの1つを参照していますFunction#applyConsumer#accept、またはRunnable#runメソッドは スローされた例外 のために突然終了します。ステージが他のメカニズムによって例外的に完了したためではありません。

Javadocによると、

このインターフェイスは、最初に作成する、通常または例外的にを強制的に完了する、完了ステータスまたは結果を調査する、またはステージの完了を待機するためのメソッドを定義しません。 CompletionStageの実装は、必要に応じて、このような効果を達成する手段を提供する場合があります

言い換えると、このインターフェースにより、実装は、計算を突然終了することなく、例外的にステージを完了することができます。これにより、新しい行動が可能になると思います。


前から私の例を拡張すると

CompletableFuture<Void> root = new CompletableFuture<>();
CompletableFuture<Void> child = root.whenComplete((v, t) -> {
    System.out.println(t.getClass()); // class Java.io.Exception
});
child.whenComplete((v, t) -> {
    System.out.println(t.getClass()); // class Java.util.concurrent.CompletionException
});
root.completeExceptionally(new IOException("blow it up"));

childに添付された補完が、元のCompletionExceptionをラップするIOExceptionを受け取ります。これは、 Javadoc からは明らかではありません。

このステージと同じsame結果またはexceptionを持つ新しいCompletionStageを返します

全体として、completeExceptionallyからの直接の例外は直接の依存関係に渡されるようですが、依存関係の依存関係は囲みCompletionExceptionを受け取ります。

10