CompletionStage是否始终在CompletionException中包装异常? [英] Does CompletionStage always wrap exceptions in CompletionException?

查看:138
本文介绍了CompletionStage是否始终在CompletionException中包装异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

CompletionStage Javadoc声明:

The CompletionStage Javadoc states:


[...]如果一个阶段的计算突然以(未经检查的)异常或错误终止,那么所有需要完成的依赖阶段异常完成,使用CompletionException将异常作为其原因。

[...] if a stage's computation terminates abruptly with an (unchecked) exception or error, then all dependent stages requiring its completion complete exceptionally as well, with a CompletionException holding the exception as its cause.

看作异常完成总是在<$ c $中包装异常c> CompletionException 为什么 exceptionally() whenComplete() handle()将异常表示为 Throwable 而不是 CompletionException

Seeing as exceptional completions always wrap exceptions in CompletionException why do exceptionally(), whenComplete() and handle() represent the exception as Throwable instead of CompletionException?

这很重要,因为它可以防止人们直接在这些方法中重新抛出异常。

This matters because it prevents one from directly re-throwing exceptions inside these methods.

是否可以这些方法接收 CompletionException 以外的异常或者我可以安全地强制转换为这种类型吗?

Is it possible for these methods to receive an exception other than CompletionException? Or can I safely force a cast to this type?

(我在本地运行了一些测试,以及挖掘CompletableFuture源代码,乍一看,我做的没有看到如何抛出任何其他类型的异常。)

(I ran some tests locally, as well as dig through the CompletableFuture source-code and, at first glance, I do not see how any other type of exception could be thrown.)

推荐答案


这些是否可能接收
以外的例外的方法 CompletionException

是,有可能并且您不应该在没有 instanceof 检查(或查看您的使用情况)的情况下转换为 CompletionException

Yes, it is possible and you shouldn't cast to CompletionException without an instanceof check (or a review of your usage).

以此为例

CompletableFuture<Void> root = new CompletableFuture<>();
root.whenComplete((v, t) -> {
    System.out.println(t.getClass()); // class java.io.IOException
});
root.completeExceptionally(new IOException("blow it up"));

whenComplete 将收到 IOException 而不是 CompletionException 包装它。相同的行为适用于异常句柄

whenComplete will receive the IOException rather than a CompletionException wrapping it. The same behavior applies to exceptionally and handle.

阶段的计算在Javadoc中定义:

A stage's computation is defined in the Javadoc:


阶段执行的计算可能是表示为函数
消费者 Runnable (使用名称包括apply,
accept或run的方法),具体取决于它是否需要
参数和/或产生结果。

The computation performed by a stage may be expressed as a Function, Consumer, or Runnable (using methods with names including apply, accept, or run, respectively) depending on whether it requires arguments and/or produces results.

我相信这句话


如果一个阶段的计算突然终止(未经检查)
异常或错误

if a stage's computation terminates abruptly with an (unchecked) exception or error

指的是函数#apply 中的一个, Consumer #accept Runnable#run 抛出异常 ,不是因为一个阶段通过其他机制异常完成。

is referring to one of those Function#apply, Consumer#accept, or Runnable#run methods terminating abruptly because of a thrown exception, not because a stage completed exceptionally through some other mechanism.

另请注意,Javadoc说

Note also that the Javadoc says


此接口未定义方法最初创建,
强行正常完成或异常,探测完成
状态或结果,或等待完成阶段。实现
CompletionStage 可以提供实现此类效果的方法,因为
合适

This interface does not define methods for initially creating, forcibly completing normally or exceptionally, probing completion status or results, or awaiting completion of a stage. Implementations of CompletionStage may provide means of achieving such effects, as appropriate

换句话说,该接口允许实现异常完成阶段而不会突然终止任何计算。我认为这允许新的行为。

In other words, the interface allows implementations to complete stages exceptionally without abruptly terminating any computation. I think this allows for new behavior.

如果我们从之前扩展我的例子

If we extend my example from before

CompletableFuture<Void> root = new CompletableFuture<>();
CompletableFuture<Void> child = root.whenComplete((v, t) -> {
    System.out.println(t.getClass()); // class java.io.Exception
});
child.whenComplete((v, t) -> {
    System.out.println(t.getClass()); // class java.util.concurrent.CompletionException
});
root.completeExceptionally(new IOException("blow it up"));

您会注意到孩子所附的完成收到 CompletionException 包装原始 IOException 。对于我来说,这对 Javadoc ,表示

You'll notice the completion attached to the child receives a CompletionException wrapping the original IOException. This isn't obvious to me from the Javadoc, which states


返回一个新的 CompletionStage 相同结果或异常
此阶段

Returns a new CompletionStage with the same result or exception as this stage

总而言之,似乎将来自 completeExceptionally 的原始异常传递给直接家属,而受抚养人的家属则收到一个封闭的 CompletionException

All in all, it seems like the raw exception from a completeExceptionally is passed down to direct dependents, while dependents of dependents receive an enclosing CompletionException.

这篇关于CompletionStage是否始终在CompletionException中包装异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆