英文:
simple completableFuture.exceptionally() not triggered when completing exceptionally()
问题
我不理解一些基础的东西。
public static void main(String[] args) {
CompletableFuture<String> cf = new CompletableFuture<>();
cf = cf.exceptionally(throwable -> "inside exceptionally");
cf.completeExceptionally(new IOException());
String s = "im empty";
try {
s = cf.get();
} catch (InterruptedException e) {
System.out.println("inside InterruptedException catch");
} catch (ExecutionException e) {
System.out.println("inside ExecutionException catch");
}
System.out.println(s);
}
我预期此代码输出为:
> inside exceptionally
实际输出为:
> inside ExecutionException catch
> im empty
根据 .exceptionally
的 Java 文档:
返回一个新的 CompletableFuture,当这个 CompletableFuture 完成时,它的结果是由异常触发的给定函数的结果,当它异常完成时触发这个 CompletableFuture 的完成;否则,如果这个 CompletableFuture 正常完成,那么返回的 CompletableFuture 也会以相同的值正常完成。
如果是这样,为什么 get
的异常捕获被触发了呢?
我以为我通过异常方式完成它会触发 .exceptionally()
方法并给我一个有效的字符串响应...
我漏掉了什么?
英文:
I dont understand something basic.
public static void main(String[] args) {
CompletableFuture<String> cf = new CompletableFuture<>();
cf = cf.exceptionally(throwable -> "inside exceptionally");
cf.completeExceptionally(new IOException());
String s = "im empty";
try {
s = cf.get();
} catch (InterruptedException e) {
System.out.println("inside InterruptedException catch");
} catch (ExecutionException e) {
System.out.println("inside ExecutionException catch");
}
System.out.println(s);
}
what i expected this code to output =
> inside exceptionally
the actual output:
> inside ExecutionException catch
> im empty
from the .exceptionally javadoc:
> Returns a new CompletableFuture that is completed when this CompletableFuture completes, with the result of the given function of the exception triggering this CompletableFuture's completion when it completes exceptionally; otherwise, if this CompletableFuture completes normally, then the returned CompletableFuture also completes normally with the same value.
If so, why did the catch of the get triggered?
I assumed me completing it exceptionally will trigger the .exceptionally() method and give me a valid String response...
What am I missing?
答案1
得分: 0
在这个片段中,
CompletableFuture<String> cf = new CompletableFuture<>();
cf = cf.exceptionally(throwable -> "inside exceptionally");
你正在创建一个 CompletableFuture
,然后稍后打算完成它,并将其引用赋值给 cf
。接着你调用的 exceptionally
返回一个新的 CompletableFuture
引用,你将其重新赋值给了 cf
,导致你失去了原始的引用。
当你稍后调用
cf.completeExceptionally(new IOException());
你这样做的对象是由 exceptionally
返回的 CompletableFuture
,而不是原始的那个。原始的
CompletableFuture<String> cf = new CompletableFuture<>();
仍然未完成。
最后,当你调用
s = cf.get();
你再次对由 exceptionally
返回的 CompletableFuture
进行操作,它被异常地完成了,带有一个 IOException
。你会注意到,如果在 catch 块中调用
e.getCause();
它会包含那个 IOException
。
你正在链接 futures,但想要操作它们两个。你想要完成原始的并且从 exceptionally()
返回的那个获取结果。所以将它们都存储在各自的变量中并进行操作。例如,
CompletableFuture<String> root = new CompletableFuture<>();
CompletableFuture<String> dependent = root.exceptionally(throwable -> "inside exceptionally");
root.completeExceptionally(new IOException());
String s = "im empty";
try {
s = dependent.get();
} catch (InterruptedException e) {
System.out.println("inside InterruptedException catch");
} catch (ExecutionException e) {
System.out.println("inside ExecutionException catch");
}
System.out.println(s);
这将打印出
inside exceptionally
意味着当 root
CompletableFuture
异常完成时,传递给 exceptionally
的 Function
会被执行。
英文:
In this snippet
CompletableFuture<String> cf = new CompletableFuture<>();
cf = cf.exceptionally(throwable -> "inside exceptionally");
you're creating a CompletableFuture
that you later intend to complete and assigning its reference to cf
. The exceptionally
you then call returns a new CompletableFuture
reference that you assign back to cf
and causing you to lose the original.
When you later call
cf.completeExceptionally(new IOException());
you're doing so on the CompletableFuture
returned by exceptionally
, not the original. The original
CompletableFuture<String> cf = new CompletableFuture<>();
remains incomplete.
Finally, when you call
s = cf.get();
you're again doing so on the CompletableFuture
returned by exceptionally
, which was completed exceptionally with an IOException
. You'll notice that if you call
e.getCause();
in that catch block, it'll contain that IOException
.
You're chaining futures, but want to operate on both of them. You want to complete the original and get the result from the the one returned by exceptionally()
. So store both of them in their own variables and do your thing. For example,
CompletableFuture<String> root = new CompletableFuture<>();
CompletableFuture<String> dependent = root.exceptionally(throwable -> "inside exceptionally");
root.completeExceptionally(new IOException());
String s = "im empty";
try {
s = dependent.get();
} catch (InterruptedException e) {
System.out.println("inside InterruptedException catch");
} catch (ExecutionException e) {
System.out.println("inside ExecutionException catch");
}
System.out.println(s);
which will print
inside exceptionally
meaning the Function
passed to exceptionally
was executed when the root
CompletableFuture
was completed exceptionally.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论