Ond*_* K. 6 java exception java-8 completable-future
假设我想在遇到特定异常时使用某个值进行恢复,否则返回带有异常的失败未来。我希望是这样的:
public static void main(String[] args) {
CompletableFuture
.supplyAsync(FuturesExample::fetchValue)
.exceptionally(throwable -> {
if (throwable instanceof RuntimeException) {
return "All good";
}
throw throwable; // does not compile
});
}
public static String fetchValue() {
// code that potentially throws an exception
return "value";
}
Run Code Online (Sandbox Code Playgroud)
如果fetchValue函数会抛出一个已检查的异常,我想在链式方法中处理它。return throwable和都试过了throw throwable,但都没有编译。是否CompletableFuture为这种情况提供了任何解决方案?我知道Function作为exceptionally方法参数的接口不会抛出任何异常 - 在这种情况下,我只想返回已经失败的未来。我想找到一个使用 Java 8 的解决方案。
在这种情况下,不可能收到受检异常,因为前一个阶段是基于 a 的Supplier,不允许抛出受检异常。
因此,您可以处理所有未经检查的异常并AssertionError为应该不可能的 throwable引发一个:
CompletableFuture
.supplyAsync(FuturesExample::fetchValue)
.exceptionally(throwable -> {
if (throwable instanceof RuntimeException) {
return "All good";
}
if(throwable instanceof Error) throw (Error)throwable;
throw new AssertionError(throwable);
});
Run Code Online (Sandbox Code Playgroud)
否则,您可能会认为后续阶段以及 的调用者join()将获得所有异常,除非CompletionException并CancellationException包装在 a 中CompletionException。例如当我使用
public static void main(String[] args) {
CompletableFuture<String> f = CompletableFuture
.supplyAsync(FuturesExample::fetchValue)
.exceptionally(throwable -> {
if(throwable instanceof RuntimeException) {
throw (RuntimeException)throwable;
}
throw new Error();
});
f.whenComplete((s,t) -> {
if(t != null) {
System.err.println("in whenComplete handler ");
t.printStackTrace();
}
});
System.err.println("calling join()");
f.join();
}
public static String fetchValue() {
throw new IllegalStateException("a test is going on");
}
Run Code Online (Sandbox Code Playgroud)
我得到
CompletableFuture
.supplyAsync(FuturesExample::fetchValue)
.exceptionally(throwable -> {
if (throwable instanceof RuntimeException) {
return "All good";
}
if(throwable instanceof Error) throw (Error)throwable;
throw new AssertionError(throwable);
});
Run Code Online (Sandbox Code Playgroud)
所以我可以CompletionException用于包装任意的 throwables,利用CompletionException不会再次包装的事实。所以如果我使用
public static void main(String[] args) {
CompletableFuture<String> f = CompletableFuture
.supplyAsync(FuturesExample::fetchValue)
.exceptionally(throwable -> {
if(throwable instanceof CompletionException)
throwable = throwable.getCause();
System.err.println("wrapping '"+throwable+"' inside exceptionally");
throw new CompletionException(throwable);
});
f.whenComplete((s,t) -> {
if(t != null) {
System.err.println("in whenComplete handler ");
t.printStackTrace();
}
});
System.err.println("calling join()");
f.join();
}
public static String fetchValue() {
throw new IllegalStateException("a test is going on");
}
Run Code Online (Sandbox Code Playgroud)
我得到
public static void main(String[] args) {
CompletableFuture<String> f = CompletableFuture
.supplyAsync(FuturesExample::fetchValue)
.exceptionally(throwable -> {
if(throwable instanceof RuntimeException) {
throw (RuntimeException)throwable;
}
throw new Error();
});
f.whenComplete((s,t) -> {
if(t != null) {
System.err.println("in whenComplete handler ");
t.printStackTrace();
}
});
System.err.println("calling join()");
f.join();
}
public static String fetchValue() {
throw new IllegalStateException("a test is going on");
}
Run Code Online (Sandbox Code Playgroud)
这在堆栈跟踪中略有不同,但对接收/捕获异常的代码没有影响,因为在任何一种情况下,它都是CompletionException一个IllegalStateException.
所以回到你的问题的例子,你可以使用
CompletableFuture
.supplyAsync(FuturesExample::fetchValue)
.exceptionally(throwable -> {
if (throwable instanceof RuntimeException) { // includes CompletionException
return "All good";
}
throw new CompletionException(throwable);
});
Run Code Online (Sandbox Code Playgroud)
由于CompletionException是 a RuntimeException,此代码处理它并避免将 a 包装CompletionException在 another 中CompletionException。否则,模式将是
.exceptionally(throwable -> {
if (some condition) {
return some value;
}
throw throwable instanceof CompletionException?
(CompletionException)throwable: new CompletionException(throwable);
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4960 次 |
| 最近记录: |