【问题标题】:How to map a "Try with resources" exception type?如何映射“使用资源尝试”异常类型?
【发布时间】:2017-03-23 14:33:20
【问题描述】:

在 Cyclops React “尝试使用资源”块中,我想将 IOException 映射到自定义异常类型。我也用 Javaslang 尝试过,但似乎不太灵活,因为它对所有异常都一视同仁。

代码示例:

private static Try<String, ConnectionError> readString() {
    // Socket is a thread-local static field
    final Try<String, IOException> string = Try.catchExceptions(IOException.class)
            .init(() -> new BufferedReader(new InputStreamReader(socket.get().getInputStream())))
            .tryWithResources(BufferedReader::readLine);

    return string.isSuccess() ? Try.success(string.get()) :
            Try.failure(new ConnectionError("Could not read from server", string.failureGet()));
}

这可以用更优雅的方式完成吗?或者没有任何意义,最好返回Try&lt;String, IOException&gt;

免责声明:我是一个使用 Cyclops React 库和一般函数式编程的新手,所以我可能对概念有严重的误解。

【问题讨论】:

    标签: java functional-programming vavr cyclops-react


    【解决方案1】:

    从 Javaslang 2.1.0 开始,可以执行以下操作:

    Try<String> of = Try.withResources(() -> new BufferedReader(new InputStreamReader(socket.get().getInputStream())))
                        .of(BufferedReader::readLine)
                        .mapFailure(
                            Case(instanceOf(IOException.class), ConnectionError::new)
                        );
    

    即我们添加了Try.withResources 功能,现在能够映射故障。

    mapFailure 方法采用可变数量的匹配案例。当异常不匹配(因此未映射)时,原始异常仍然存在。

    我认为在 Try 签名中包含异常类型是没有意义的,例如Try&lt;String, IOException&gt;,因为计算可能会抛出几个异常之一。

    指定一组可能的异常类型也无济于事,因为当编译器计算泛型的上限时类型信息会丢失。

    免责声明:我是 Javaslang 的创造者

    【讨论】:

    • 谢谢丹尼尔。目前您是否知道该版本何时可用?
    • 它将与即将发布的 2.1.0-beta(4 月初)一起发布。目前有 21 个针对 2.1.0 的未解决问题。我看到 5 个需要一些时间的问题,以及一些必须完成的向后兼容性修复,直到我们可以发布它。简而言之,我的目标是 May(最终版本)。
    • 如果这个答案包含相关的导入将会非常有帮助,因为标识符足够通用,很难知道从哪里开始。
    【解决方案2】:

    您可以使用'visit'方法来转换故障类型。所有 cyclops-react 类型都有一个访问方法或“catamorphism”。这允许您匹配该数据类型的内部状态。在 Try 的情况下,它需要两个函数,一个在 Try 成功时执行,另一个在失败时执行。

    private static Try<String, ConnectionError> readString() {
        // Socket is a thread-local static field
        return Try.catchExceptions(IOException.class)
                  .init(() -> new BufferedReader(new InputStreamReader(socket.get().getInputStream())))
                  .tryWithResources(BufferedReader::readLine)
                  .visit(Try::success,
                         e->Try.failure(new ConnectionError("Could not read from server", e));
    }
    

    Vavr / Javaslang Try 和 cyclops-react Try 之间存在很大的概念/设计差异。一种或另一种可能更适合不同的用例。 (Daniel 可以概述 Vavr Try 背后的基本原理)。

    cyclops-react 版本仅处理显式命名的异常,并保留该类型信息。因此 cyclops-react Try 采用两个通用参数,一个用于成功类型,一个用于最一般的推断异常类型。

    cyclops-react Try 通常不会在正在进行的流畅操作(例如 map / flatMap 等)中捕获异常,尽管它可以配置为这样做。

    cyclops-react Try 的核心设计目标是避免隐藏错误。这个StackExchange answer有更详细的概述。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-04
      • 1970-01-01
      • 1970-01-01
      • 2012-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多