2014-12-11 8 views
18

Ho riscontrato uno strano comportamento di Java 8 CompletableFuture.exceptionally method. Se eseguo questo codice, funziona benissimo e stampe java.lang.RuntimeExceptionComportamento sorprendente di Java 8 CompletableFuture eccezionalmente metodo

CompletableFuture<String> future = new CompletableFuture<>(); 

future.completeExceptionally(new RuntimeException()); 

future.exceptionally(e -> { 
      System.out.println(e.getClass()); 
      return null; 
}); 

Ma se aggiungo un altro passo nel futuro di elaborazione, come il tipo di eccezione thenApply modifiche java.util.concurrent.CompletionException con l'eccezione originale avvolto all'interno.

CompletableFuture<String> future = new CompletableFuture<>(); 

future.completeExceptionally(new RuntimeException()); 

future.thenApply(v-> v).exceptionally(e -> { 
      System.out.println(e); 
      return null; 
}); 

C'è qualche motivo per cui questo dovrebbe accadere? A mio parere, è abbastanza sorprendente.

risposta

20

Questo comportamento is specified in the class documentation of CompletionStage (fourth bullet):

Metodo handle permette inoltre la fase di calcolare un risultato di sostituzione che può consentire un'ulteriore elaborazione da altri stadi dipendenti. In tutti gli altri casi, se il calcolo di uno stadio termina improvvisamente con un'eccezione o un errore (non verificato), anche tutte le fasi dipendenti che richiedono il completamento completano eccezionalmente, con un CompletionException che mantiene l'eccezione come causa.

Non è che sorprendente se si considera che si potrebbe desiderare di sapere se il palco, si è invocato exceptionally su, non è riuscito o uno dei suoi prerequisiti diretti o indiretti.

1

sì, si prevede che il comportamento, ma se si desidera che l'eccezione originale che è stato lanciato da una delle fasi precedenti, si può semplicemente utilizzare questo-

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; 
}); 
Problemi correlati