问题描述
考虑以下代码 -
public class TestCompletableFuture {
BiConsumer<Integer, Throwable> biConsumer = (x,y) -> {
System.out.println(x);
System.out.println(y);
};
public static void main(String args[]) {
TestCompletableFuture testF = new TestCompletableFuture();
testF.start();
}
public void start() {
Supplier<Integer> numberSupplier = new Supplier<Integer>() {
@Override
public Integer get() {
return SupplyNumbers.sendNumbers();
}
};
CompletableFuture<Integer> testFuture = CompletableFuture.supplyAsync(numberSupplier).whenComplete(biConsumer);
}
}
class SupplyNumbers {
public static Integer sendNumbers(){
return 25; // just for working sake its not correct.
}
}
以上情况正常。但是 sendNumbers
也可以在我的情况下抛出一个已检查的异常,例如:
The above thing works fine. However sendNumbers
could also throw a checked exception in my case, like:
class SupplyNumbers {
public static Integer sendNumbers() throws Exception {
return 25; // just for working sake its not correct.
}
}
现在我想将此异常处理为 y
在我的 biConsumer
中。这将帮助我处理单个函数内的结果以及异常(如果有的话)( biConsumer
)。
Now I want to handle this exception as y
in my biConsumer
. This will help me in handling the result as well as exception (if any) inside a single function (biConsumer
).
有什么想法吗?我可以在这里或其他地方使用 CompletableFuture.exceptionally(fn)
吗?
Any ideas? Can I use CompletableFuture.exceptionally(fn)
here or anything else?
推荐答案
当您想要处理已检查的异常时,使用标准功能接口的工厂方法没有用。当您将代码捕获到lambda表达式中时,您遇到的问题是catch子句需要 CompletableFuture
实例来设置异常,而工厂方法需要供应商
,鸡肉和鸡蛋。
The factory methods using the standard functional interfaces aren’t helpful when you want to handle checked exceptions. When you insert code catching the exception into the lambda expression, you have the problem that the catch clause needs the CompletableFuture
instance to set the exception while the factory method needs the Supplier
, chicken-and-egg.
您可以使用类的实例字段在创建后允许变异,但是最后,生成的代码不是干净的,而且比基于直接 Executor
的解决方案更复杂。 说:
You could use an instance field of a class to allow mutation after creation, but in the end, the resulting code isn’t clean and more complicated that a straight-forward Executor
-based solution. The documentation of CompletableFuture
says:
因此您知道以下代码将直接处理已检查的异常时显示 CompletableFuture.supplyAsync(Supplier)
的标准行为:
so you know the following code will show the standard behavior of CompletableFuture.supplyAsync(Supplier)
while handling checked exceptions straight-forward:
CompletableFuture<Integer> f=new CompletableFuture<>();
ForkJoinPool.commonPool().submit(()-> {
try { f.complete(SupplyNumbers.sendNumbers()); }
catch(Exception ex) { f.completeExceptionally(ex); }
});
文档还说:
如果您希望遵守此约定以使解决方案更像原始 supplyAsync
方法,请将代码更改为:
If you want to adhere to this convention to make the solution even more behaving like the original supplyAsync
method, change the code to:
CompletableFuture<Integer> f=new CompletableFuture<>();
ForkJoinPool.commonPool().submit(
(Runnable&CompletableFuture.AsynchronousCompletionTask)()-> {
try { f.complete(SupplyNumbers.sendNumbers()); }
catch(Exception ex) { f.completeExceptionally(ex); }
});
这篇关于使用CompletableFuture处理Java 8供应商异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!