2015-07-10 4 views
8

In questo codice:Java funzionale - Interazione tra whenComplete ed eccezionalmente

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

Quando v'è una deroga doSomethingThatMightThrowAnException, sono entrambi doSomethingElse e handleException corsa, o è l'eccezione consumato sia dal whenComplete o exceptionally?

EDIT:

doSomethingThatMightThrowAnException restituisce un CompletableFuture, che potrebbe completeExceptionally. Questa è l'eccezione di cui sto parlando.

risposta

10

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.

0

doSomethingThatMightThrowAnException() è concatenato con .whenComplete ((result, ex) -> doSomethingElse()}) e .exceptionally (ex -> handleException (ex)); ma se lancia un'eccezione finisce proprio lì, poiché nessun oggetto sarà passato nella catena.

Ricordare che un'eccezione verrà eliminata dal chiamante, quindi a meno che doSomethingThatMightThrowAnException() non rilevi l'eccezione internamente verrà eliminata. Se questa è la tua classe dovresti sapere se getta, se non controlla i documenti per lilbraris che usi.

1

I exceptionally metodo afferma:

restituisce un nuovo CompletableFuture che si completa quando questo CompletableFuture completa, con il risultato della funzione data della eccezione innescare completamento di questa CompletableFuture quando completa eccezionalmente; in caso contrario, se CompletableFuture viene completato normalmente, anche il CompletableFuture restituito viene completato normalmente con lo stesso valore. Nota: versioni più flessibili di questa funzionalità sono disponibili utilizzando i metodi quandoCompleta e gestisce.

questo non è, secondo me scritto nel modo più chiaro inglese, ma direi che significa che se viene generata un'eccezione verrà attivato l'solo l'azione exceptionally. Se non viene lanciata alcuna eccezione, verrà eseguita solo l'azione normal.