我是Java的新手,所以我希望这不是微不足道的,但是我真的找不到我想要的东西。
我有一个引发异常的函数:
public String foo(String s) throws MyException {
if ("a".equals(s)){
return s;
} else {
throw new MyException("Oh no!");
}
}
当MyException只是:
class MyException extends Exception{
String str1;
MyException(String str2) {
str1=str2;
}
public String toString(){
return ("MyException Occurred: "+str1) ;
}
}
现在,我有另一个在CompletableFuture内部调用foo的方法:
private CompletableFuture<String> test() throws Exception{
return CompletableFuture.supplyAsync(() -> foo("b"));
}
但是foo引发异常,因此这里出现编译错误,因为对foo的调用是未处理的异常。
我只想抛出原始(内部)异常。我该怎么办?
答案 0 :(得分:3)
您有两个问题。
您不能在lambda表达式中引发检查的异常,请参见例如this answer。要解决此问题,您可以在lambda表达式中使用catch块,也可以使用运行时异常。
supplyAsync(() -> foo("b"))
表示它将在以后的某个时间(例如,稍后)在另一个线程中异步运行。当您对结果调用.get()
时。因此,test()
方法引发异常没有意义。
答案 1 :(得分:1)
方法foo
不得引发已检查的异常,而应引发不可声明的RuntimeException。
class MyException extends RuntimeException
创建Future不会执行foo
,将在另一个调用中执行。所以不能扔东西。
private static CompletableFuture<String> test() {
return CompletableFuture.supplyAsync(() -> foo("b"));
}
get()
或get
可能会等待超时。这将通过将引发的MyException
包装为ExecutionException
来传递。{p1
尝试{ test()。get(); } catch(InterruptedException e){ e.printStackTrace(); } catch(ExecutionException e){ e.getCause()。printStackTrace(); }
别忘了用exceptionally
拦截异常:
try {
String s = test().exceptionally(throwable -> {
throwable.getCause().printStackTrace();
return "xxx"; }).get();
System.err.println("s=" + s);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
答案 2 :(得分:0)
您需要在CompletableFuture的实现中提供此选中的MyException异常,因为它是“选中的异常”,这意味着它是从Exception类派生的。要么提供它,要么将MyException更改为从RuntimeException扩展,那么您就不必提供它(捕获)。