Il documentation of whenComplete
dice:
restituisce un nuovo CompletionStage con lo stesso risultato o eccezione in quanto questa fase, che esegue l'azione data in cui questa fase completa.
(sottolineatura mia)
Ciò implica che un'eccezione non viene inghiottito da questa fase in quanto si suppone di avere lo stesso risultato o eccezione.Tuttavia, potreste essere sorpresi dal fatto che le fasi successive riceveranno l'eccezione di una precedente fase avvolto all'interno di un CompletionException
, come discusso here, quindi non è esattamente la stessa eccezione:
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());
stamperà:
stage 2: null java.io.IOException
stage 3: java.util.concurrent.CompletionException: java.io.IOException
noti che è possibile accodare sempre più azioni su un palco, invece di concatenamento poi:
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
Ovviamente, dal momento che non esiste alcuna dipendenza tra lo stage 2a
e 2b
, non esiste un ordinamento tra di loro e nel caso di un'azione asincrona, possono essere eseguiti contemporaneamente.