Java 8 CompletableFuture.exceptionallyメソッドの奇妙な動作に遭遇しました。このコードを実行すると、正常に動作し、Java.lang.RuntimeException
を出力します。
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException());
future.exceptionally(e -> {
System.out.println(e.getClass());
return null;
});
しかし、将来の処理にthenApply
などの別のステップを追加すると、例外タイプはJava.util.concurrent.CompletionException
に変更され、元の例外が内部にラップされます。
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException());
future.thenApply(v-> v).exceptionally(e -> {
System.out.println(e);
return null;
});
これが起こるべき理由はありますか?私の意見では、それは非常に驚くべきことです。
この動作 CompletionStage
(4番目の箇条書き)のクラスドキュメントで指定されています :
メソッド
handle
は、さらに、ステージが置換結果を計算できるようにします。これにより、他の依存ステージによるさらなる処理が可能になります。他のすべての場合、ステージの計算が(チェックされていない)例外またはエラーで突然終了した場合、その完了を必要とするすべての依存ステージも例外を完了し、例外を保持しますCompletionException
その原因として。
exceptionally
を呼び出したステージが失敗したか、そのいずれかがwantであるかどうかを知りたいと考えても驚くにはあたらない直接または間接の前提条件。
はい、動作は予期されていますが、前のステージのいずれかからスローされた元の例外が必要な場合は、単にこれを使用できます
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException());
future.thenApply(v-> v).exceptionally(e -> {
System.out.println(e.getCause()); // returns a throwable back
return null;
});