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

问题描述

Javadoc声明:

The CompletionStage Javadoc states:

看作异常完成总是在<$ 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.)

推荐答案

是,有可能并且您不应该在没有 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:

我相信这句话

指的是函数#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

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

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 。对于我来说,这对,表示

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

总而言之,似乎将来自 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中包装异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 21:53