2014-12-11 9 views
18

Ich habe seltsames Verhalten der Java 8 CompletableFuture.exceptionally Methode begegnet. Wenn ich diesen Code ausführen, funktioniert es gut und Drucke java.lang.RuntimeExceptionÜberraschendes Verhalten von Java 8 CompletableFuture ausnahmsweise Methode

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

future.completeExceptionally(new RuntimeException()); 

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

Aber wenn ich einen weiteren Schritt in die Zukunft Verarbeitung hinzufügen, wie thenApply die Ausnahmetyp Änderungen java.util.concurrent.CompletionException mit der ursprünglichen Ausnahme innen gewickelt.

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

future.completeExceptionally(new RuntimeException()); 

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

Gibt es einen Grund, warum dies passieren sollte? Meiner Meinung nach ist das ziemlich überraschend.

Antwort

20

Dieses Verhalten is specified in the class documentation of CompletionStage (fourth bullet):

Method handle erlaubt zusätzlich die Stufe ein Ersatzergebnis zu berechnen, die von anderen abhängigen Stufen Weiterverarbeitung ermöglichen kann. Wenn in allen anderen Fällen die Berechnung einer Stufe abrupt mit einer (nicht aktivierten) Ausnahme oder einem Fehler endet, werden alle abhängigen Stufen, die ihre Beendigung erfordern, ebenfalls ausnahmsweise beendet, wobei CompletionException die Ausnahme als Ursache hat.

Es ist nicht so überraschend, wenn man bedenkt, dass Sie, ob die Bühne kann wollen wissen, Sie aufgerufen haben exceptionally auf, ausgefallen oder einer seiner direkten oder indirekten Voraussetzungen.

1

ja, wird das Verhalten erwartet, aber wenn Sie die ursprüngliche Ausnahme mögen, die von einem der vorhergehenden Stufen geworfen wurde, können Sie einfach this-

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; 
}); 
Verwandte Themen