调用 supplyAsync 时尝试捕获
Try & Catch When Calling supplyAsync
我是 CompletableFuture 的新手,我想调用一个可以抛出异常的方法 MetadataLoginUtil::login。但是,尽管我写了'exceptionally',但下面的代码没有编译。它说我必须将 MetadataLoginUtil::login' 包装在 try & catch 中。
请指教。
先谢谢了!
public void run() throws ConnectionException {
CompletableFuture<Void> mt = CompletableFuture.supplyAsync(MetadataLoginUtil::login)
.exceptionally(e -> {
System.out.println(e);
return null;
})
.thenAccept(e -> System.out.println(e));
}
CompletableFuture.supplyAsync(Supplier<U>)
需要一个 java.util.function.Supplier<U>
实例,并且 Supplier.get()
方法的签名不允许检查异常。要清楚地看到这一点,请注意 CompletableFuture.supplyAsync(MetadataLoginUtil::login)
等同于
CompletableFuture<Void> mt = CompletableFuture.supplyAsync(new Supplier<Void>() {
@Override
public Void get() {
return MetadataLoginUtil.login();
}
})
显然无法编译。
您可以在 Supplier
中处理异常,将 CompletableFuture.supplyAsync(MetadataLoginUtil::login).exceptionally(e -> {System.out.println(e); return null; } )
更改为
CompletableFuture.supplyAsync(() -> {
try {
return MetadataLoginUtil.login();
} catch (Exception e) {
System.out.println(e);
return null;
}
})
它不是很漂亮,但是 CompletableFuture
的 API 似乎不能很好地处理检查异常。
这不是 CompletableFuture
一般工作方式的缺陷,而是便利方法的缺陷,所有方法都使用不允许检查异常的功能接口。您可以使用另一种 supplyAsync
方法解决此问题:
public static <T> CompletableFuture<T> supplyAsync(Callable<T> c) {
CompletableFuture<T> f=new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
try { f.complete(c.call()); } catch(Throwable t) { f.completeExceptionally(t); }
});
return f;
}
这基本上与原来的 supplyAsync
相同,但允许检查异常。因此,您可以像在最初的尝试中一样正确使用它,仅重定向初始 supplyAsync
调用。
CompletableFuture<Void> mt = supplyAsync(MetadataLoginUtil::login)
.exceptionally(e -> { System.out.println(e); return null; } )
.thenAccept(e -> System.out.println(e));
我是 CompletableFuture 的新手,我想调用一个可以抛出异常的方法 MetadataLoginUtil::login。但是,尽管我写了'exceptionally',但下面的代码没有编译。它说我必须将 MetadataLoginUtil::login' 包装在 try & catch 中。
请指教。 先谢谢了!
public void run() throws ConnectionException {
CompletableFuture<Void> mt = CompletableFuture.supplyAsync(MetadataLoginUtil::login)
.exceptionally(e -> {
System.out.println(e);
return null;
})
.thenAccept(e -> System.out.println(e));
}
CompletableFuture.supplyAsync(Supplier<U>)
需要一个 java.util.function.Supplier<U>
实例,并且 Supplier.get()
方法的签名不允许检查异常。要清楚地看到这一点,请注意 CompletableFuture.supplyAsync(MetadataLoginUtil::login)
等同于
CompletableFuture<Void> mt = CompletableFuture.supplyAsync(new Supplier<Void>() {
@Override
public Void get() {
return MetadataLoginUtil.login();
}
})
显然无法编译。
您可以在 Supplier
中处理异常,将 CompletableFuture.supplyAsync(MetadataLoginUtil::login).exceptionally(e -> {System.out.println(e); return null; } )
更改为
CompletableFuture.supplyAsync(() -> {
try {
return MetadataLoginUtil.login();
} catch (Exception e) {
System.out.println(e);
return null;
}
})
它不是很漂亮,但是 CompletableFuture
的 API 似乎不能很好地处理检查异常。
这不是 CompletableFuture
一般工作方式的缺陷,而是便利方法的缺陷,所有方法都使用不允许检查异常的功能接口。您可以使用另一种 supplyAsync
方法解决此问题:
public static <T> CompletableFuture<T> supplyAsync(Callable<T> c) {
CompletableFuture<T> f=new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
try { f.complete(c.call()); } catch(Throwable t) { f.completeExceptionally(t); }
});
return f;
}
这基本上与原来的 supplyAsync
相同,但允许检查异常。因此,您可以像在最初的尝试中一样正确使用它,仅重定向初始 supplyAsync
调用。
CompletableFuture<Void> mt = supplyAsync(MetadataLoginUtil::login)
.exceptionally(e -> { System.out.println(e); return null; } )
.thenAccept(e -> System.out.println(e));