CompletableFuture exceptionally() 和 handle() 吞下 RuntimeException?
CompletableFuture exceptionally() and handle() swallowing RuntimeException?
我有以下内容:
cflst.addAll(asList(
supplyAsync(() -> mytask.getComp("comp"), executor)
.thenAccept(comp -> helper.mapStuff(comp))
.exceptionally(ex -> {
sout("Some Error"); // Never print
return null;
})
.handle((comp, throwable) -> {
sout("Error here" + comp); //always prints regarless of exception
return null;
}),
...
));
CompletableFuture.allOf(cflst.toArray(new CompletableFuture[0])).join();
和MyTask.getComp
方法
CompX getComp(String id) {
client.getData(id);
}
Client.getData()
SomeX getData(String id) {
throw new MyCustomRuntimeException("Blew Up");
}
我以为在myComp
方法抛出异常时,exceptionally()
块得到了异常。但是好像没有。
此外,无论异常如何,handle()
总是被调用 !?!?!
我希望能够捕获任何异常并根据需要进行处理(重新抛出或吞下)。
更新
当我在 getComp
方法中捕获异常然后重新抛出它时,exceptionally
块被执行。但是不确定为什么它没有被执行,当异常在 getData
方法中向下抛出一级时?
handle()
方法创建的stage无论有无异常都会执行,而exceptionally()
stage只在有异常时才执行
我无法重现您的错误,只要未捕获到异常,exceptionally
块就会为我执行。
在我看来,您应该使用 handle
或 exceptionally
。
handle()
方法使您能够在异常时提供默认值,exceptionally()
方法与 handle 类似但更简洁
在您的示例中,您正在按顺序编写 CompletableFuture
s。
在 .exceptionally()
之后,您将得到一个产生 null
而不是抛出异常的未来。因此,后续的.handle()
永远不会观察到异常。
如果您希望 .handle()
获得相同的异常,您必须在调用 .exception()
的同一未来调用它。例如,使用一个变量来存储你在 .thenAccept()
之后得到的未来,然后在其上组合 .exceptionally()
和 .handle()
,而不是按顺序组合。
但是,您应该在 .exceptionally()
和 .handle()
之间选择:
.exceptionally()
通常用于return一个默认值而不是让异常通过
.handle()
通常用于记录,转换 and/or 像 catch
块一样包装异常;如果你想让异常通过,不要忘记重新抛出
对于像 finally
块这样的清理操作,.whenComplete()
更合适。
我有以下内容:
cflst.addAll(asList(
supplyAsync(() -> mytask.getComp("comp"), executor)
.thenAccept(comp -> helper.mapStuff(comp))
.exceptionally(ex -> {
sout("Some Error"); // Never print
return null;
})
.handle((comp, throwable) -> {
sout("Error here" + comp); //always prints regarless of exception
return null;
}),
...
));
CompletableFuture.allOf(cflst.toArray(new CompletableFuture[0])).join();
和MyTask.getComp
方法
CompX getComp(String id) {
client.getData(id);
}
Client.getData()
SomeX getData(String id) {
throw new MyCustomRuntimeException("Blew Up");
}
我以为在myComp
方法抛出异常时,exceptionally()
块得到了异常。但是好像没有。
此外,无论异常如何,handle()
总是被调用 !?!?!
我希望能够捕获任何异常并根据需要进行处理(重新抛出或吞下)。
更新
当我在 getComp
方法中捕获异常然后重新抛出它时,exceptionally
块被执行。但是不确定为什么它没有被执行,当异常在 getData
方法中向下抛出一级时?
handle()
方法创建的stage无论有无异常都会执行,而exceptionally()
stage只在有异常时才执行
我无法重现您的错误,只要未捕获到异常,exceptionally
块就会为我执行。
在我看来,您应该使用 handle
或 exceptionally
。
handle()
方法使您能够在异常时提供默认值,exceptionally()
方法与 handle 类似但更简洁
在您的示例中,您正在按顺序编写 CompletableFuture
s。
在 .exceptionally()
之后,您将得到一个产生 null
而不是抛出异常的未来。因此,后续的.handle()
永远不会观察到异常。
如果您希望 .handle()
获得相同的异常,您必须在调用 .exception()
的同一未来调用它。例如,使用一个变量来存储你在 .thenAccept()
之后得到的未来,然后在其上组合 .exceptionally()
和 .handle()
,而不是按顺序组合。
但是,您应该在 .exceptionally()
和 .handle()
之间选择:
.exceptionally()
通常用于return一个默认值而不是让异常通过.handle()
通常用于记录,转换 and/or 像catch
块一样包装异常;如果你想让异常通过,不要忘记重新抛出
对于像 finally
块这样的清理操作,.whenComplete()
更合适。