当前位置: 首页 > 面试题库 >

来自CompletableFuture的抛出异常

劳夕
2023-03-14
问题内容

我有以下代码:

// How to throw the ServerException?
public void myFunc() throws ServerException{
    // Some code
    CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
        try {
            return someObj.someFunc();
        } catch(ServerException ex) {
            // throw ex; gives an error here.
        }
    }));
    // Some code
}

someFunc()抛出一个ServerException。我不想在这里处理此问题,但是将异常从抛出someFunc()给的调用者myFunc()


问题答案:

您的代码建议您稍后以相同的方法使用异步操作的结果,因此CompletionException无论如何都必须进行处理,因此一种处理方法是

public void myFunc() throws ServerException {
    // Some code
    CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
        try { return someObj.someFunc(); }
        catch(ServerException ex) { throw new CompletionException(ex); }
    });
    // Some code running in parallel to someFunc()

    A resultOfA;
    try {
        resultOfA = a.join();
    }
    catch(CompletionException ex) {
        try {
            throw ex.getCause();
        }
        catch(Error|RuntimeException|ServerException possible) {
            throw possible;
        }
        catch(Throwable impossible) {
            throw new AssertionError(impossible);
        }
    }
    // some code using resultOfA
}

在的异步处理中抛出的所有异常Supplier都将CompletionException在调用时包装为一个join,除了ServerException我们已经包装在一个CompletionException

当重新引发的原因时CompletionException,我们可能会遇到未检查的异常,即Erroror的子类RuntimeException或我们的自定义检查的异常ServerException。上面的代码通过多次捕获来处理所有这些错误,然后将它们重新抛出。由于声明的返回类型getCause()Throwable,尽管我们已经处理了所有可能的类型,但编译器仍要求我们处理该类型。直接的解决方案是将包裹在包装中的这个实际上不可能的可抛物抛出AssertionError

或者,我们可以为自定义异常使用将来的替代结果:

public void myFunc() throws ServerException {
    // Some code
    CompletableFuture<ServerException> exception = new CompletableFuture<>();
    CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
        try { return someObj.someFunc(); }
        catch(ServerException ex) {
            exception.complete(ex);
            throw new CompletionException(ex);
        }
    });
    // Some code running in parallel to someFunc()

    A resultOfA;
    try {
        resultOfA = a.join();
    }
    catch(CompletionException ex) {
        if(exception.isDone()) throw exception.join();
        throw ex;
    }

    // some code using resultOfA
}

该解决方案将所有“意外”的可扔物以它们的包装形式重新抛出,但仅将自定义ServerExceptionexception将来通过的原始形式抛出。请注意,在查询未来之前,我们必须确保a已完成操作(例如join()先调用)exception,以避免出现竞争情况。



 类似资料:
  • 问题内容: 包含多个有关将检查的异常与混合使用的问题。 虽然一些答案暗示使用其方法会导致难以阅读的用户代码。 我将使用此空间来提供可提高可读性的替代解决方案。 请注意,此问题特定于CompletableFuture。 这使我们能够提供更广泛地不扩展到lambda表达式的解决方案。 问题答案: 给定实用程序类(下面提供),用户可以无缝地抛出检查异常: 由lambda引发的任何异常(是否经过检查)都将

  • 假设我想在收到特定异常时恢复某个值,否则返回失败的未来。我希望是这样的: 如果函数会抛出检查过的异常,我想在链式方法中处理它。我尝试过和,但都无法编译。是否为这种情况提供了任何解决方案?我知道接口是方法的参数,它不会抛出任何异常——在这种情况下,我只想返回已经失败的未来。我想找到使用Java8的解决方案。

  • 这个问题是针对Java和< code>CompletableFuture的。 如果我有一个像下面这样的异步方法, 如果步骤#1中的代码抛出,的调用者将在获得它返回的之前获得异常,而如果步骤#2中返回的中的代码抛出,调用者将仅在与返回的交互时获得异常。 这表明的调用方应该编写一些复杂的异常处理代码来处理这两种情况。 下面是另一个异步方法的示例,,该方法调用并返回它返回的字符串长度: 我的问题是: <

  • 抛出异常的行为是否可能抛出不同的异常? 为了抛出异常,必须(可选地)分配新对象,并调用其构造函数(隐式调用fillinstacktrace)。在某些情况下,听起来像addSupressed也被称为。那么如果没有足够的内存会发生什么呢?JVM是否需要预分配内置异常?例如,(1/0)会抛出OutOfMemoryError而不是ArithmeticException吗? 此外,构造函数是一个方法调用,因

  • 本文向大家介绍java 异常之手动抛出与自动抛出的实例讲解,包括了java 异常之手动抛出与自动抛出的实例讲解的使用技巧和注意事项,需要的朋友参考一下 java异常处理机制的两类 1、抓:异常的处理,有两种方式 ① try-catch-finally ② throws 2、抛: ① 自动抛出 可以理解为所有没有使用throw关键字的异常处理都是自动抛出,由jvm进行判断和抛出。 ②手动抛出 thr

  • "CATCH"应该严格地在"扔"之后叫吗?" 例1: 错误: 找不到方法“接收器”:没有方法缓存,也没有^在/tmp/739536251/main块中查找_方法。pl6第11行 例2: 无误