我使用java 8的可完成的未来,我希望能够接受未来抛出的异常,并将其转换为另一个异常。
一旦发生异常,我尝试的所有复合材料似乎都会被短路。
例如,使用scala future,我可以这样做:
scala.concurrent.Future<Object> translatedException = ask.recover(new Recover<Object>() {
@Override public Object recover(final Throwable failure) throws Throwable {
if (failure instanceof AskTimeoutException) {
throw new ApiException(failure);
}
throw failure;
}
}, actorSystem.dispatcher());
我希望能够在未来的java复合块中模仿它。这可能吗?
答案 0 :(得分:2)
您可以使用CompletableFuture#handle(BiFunction)
。例如
CompletableFuture<String> ask = CompletableFuture.supplyAsync(() -> {
throw new IndexOutOfBoundsException();
});
CompletableFuture<String> translatedException = ask.handle((r, e) -> {
if (e != null) {
if (e instanceof IndexOutOfBoundsException) {
throw new IllegalArgumentException();
}
throw (RuntimeException) e; // this is sketchy, handle it differently, maybe by wrapping it in a RuntimeException
}
return r;
});
如果ask
完成了异常,则translatedException
将完成可能已转换的异常。否则,它将具有相同的成功结果值。
关于我在代码中的评论,handle
方法需要BiFunction
未声明其apply
方法抛出Throwable
。因此,lambda身体本身不能抛出Throwable
。参数e
的类型为Throwable
,因此您无法直接throw
它。如果您知道该类型,可以将其投放到RuntimeException
,或者将其包装在RuntimeException
和throw
中。
答案 1 :(得分:0)
请注意,e 将始终是 java.util.concurrent.CompletionException
。
CompletableFuture<String> ask = CompletableFuture.supplyAsync(() -> {
throw new IndexOutOfBoundsException();
});
CompletableFuture<String> translatedException = ask.handle((r, e) -> {
if (e != null) {
if (e.getCause() instanceof IndexOutOfBoundsException) {
throw new IllegalArgumentException();
}
throw (RuntimeException) e; // this is sketchy, handle it differently, maybe by wrapping it in a RuntimeException
}
return r;
});