並行処理(CompletableFuture)難易度 高無料
次のコードの出力として正しいものを選べ。
1 import java.util.concurrent.*;
2 public class Q6 {
3 public static void main(String[] args) throws Exception {
4 CompletableFuture<Integer> cf = CompletableFuture
5 .<Integer>supplyAsync(() -> { throw new RuntimeException("boom"); })
6 .handle((res, ex) -> ex != null ? -1 : res)
7 .thenApply(n -> n + 100);
8 System.out.println(cf.get());
9 }
10 }
- A
cf.get()がExecutionExceptionをスローする - B
99 - C
-1 - D
101
正解・解説・誤答理由・ひっかけを見る▼ open
✓ 正解:B✓Gold監修
解説
supplyAsync 内の Supplier が例外を投げると、そのステージは例外完了する。
handle((res, ex) -> ...) は正常・例外のどちらの場合も必ず呼ばれるのが特徴で、
例外時は res=null, ex=例外 が渡る。本コードは ex != null なので -1 を返し、
例外を回復して正常完了の値 -1 に置き換える。続く thenApply は -1 + 100 = 99 を生成。
cf.get() は正常完了なので例外を投げず 99 を返す。- A
handleが例外を吸収して値に変換するため、下流に例外は伝播せず get() は例外を投げない。(仮にthenApplyだけなら例外が伝播し A になる ― そこが対比のポイント) - C
handleで -1 に回復した後、thenApply(+100)が必ず適用されるため最終値は -1 ではない。 - D
1 + 100としてしまう誤り。回復値は -1 なので-1 + 100 = 99。
ひっかけ:
handle と exceptionally/whenComplete の違い。handle は両ケースで呼ばれ<戻り値で次ステージの値を差し替える>。whenComplete は副作用のみで値を変えない。実機確認の答え合わせ
出力:99 (注:handleに渡るのは ex != null の真偽だけが効くため、例外がCompletionExceptionで包まれるか否かに関わらず結果は不変)
✓Gold 保有者による書き下ろし解説・実機で検証済