在CompletableFuture中的函数中引发原始(内部)异常吗?

时间:2018-10-10 21:07:02

标签: java exception java-8

我是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的调用是未处理的异常。

我只想抛出原始(内部)异常。我该怎么办?

3 个答案:

答案 0 :(得分:3)

您有两个问题。

  1. 您不能在lambda表达式中引发检查的异常,请参见例如this answer。要解决此问题,您可以在lambda表达式中使用catch块,也可以使用运行时异常。

  2. supplyAsync(() -> foo("b"))表示它将在以后的某个时间(例如,稍后)在另一个线程中异步运行。当您对结果调用.get()时。因此,test()方法引发异常没有意义。

答案 1 :(得分:1)

  1. 方法foo不得引发已检查的异常,而应引发不可声明的RuntimeException。

    class MyException extends RuntimeException
    
  2. 创建Future不会执行foo,将在另一个调用中执行。所以不能扔东西。

    private static CompletableFuture<String> test() {
        return CompletableFuture.supplyAsync(() -> foo("b"));
    }
    
  3. get()get可能会等待超时。这将通过将引发的MyException包装为ExecutionException来传递。{p1

    尝试{         test()。get();     } catch(InterruptedException e){         e.printStackTrace();     } catch(ExecutionException e){         e.getCause()。printStackTrace();     }

  4. 别忘了用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扩展,那么您就不必提供它(捕获)。