首页 > 解决方案 > 处理 Java8 流中的已检查异常

问题描述

假设您有一个公开下一个接口的 3rd 方库。

interface Mapper {

    String doMap(String input) throws CheckedException;

}

class CheckedException extends Exception {

}

我知道检查异常在 Java 中通常是一种不好的做法,但是这段代码来自第 3 方,我无法修改它。

我想结合 Java8 流 API 使用 Mapper 接口的实现。考虑下面的示例实现。

class MapperImpl implements Mapper {

    public String doMap(String input) throws CheckedException {
        return input;
    }

}

现在,例如,我想将映射器应用于字符串集合。

public static void main(String[] args) {
    List<String> strings = Arrays.asList("foo", "bar", "baz");
    Mapper mapper = new MapperImpl();

    List<String> mappedStrings = strings
            .stream()
            .map(mapper::doMap)
            .collect(Collectors.toList());
}

代码无法编译,因为 Function 不知道如何处理 doMap 声明的 CheckedException。我想出了两种可能的解决方案。

解决方案 #1 - 包装调用

.map(value -> {
                try {
                    return mapper.doMap(value);
                } catch (CheckedException e) {
                    throw new UncheckedException();
                }
            })

解决方案 #2 - 编写实用程序方法

public static final String uncheck (Mapper mapper, String input){
    try {
        return mapper.doMap(input);
    } catch (CheckedException e){
        throw new UncheckedException();
    }
}

然后我可以使用

.map(value -> Utils.uncheck(mapper, value))

在您看来,在 Java8 流的上下文中(以及在更广泛的 lambda 表达式的上下文中)处理检查异常的最佳方法是什么?

谢谢!

标签: java

解决方案


您基本上列出了两个可行的选项。

另一种选择是将检查的异常从流处理函数中抛出(“传播”或“潜入”检查的异常)。这是通过捕获已检查异常并将其重新抛出RuntimeException(通过强制转换)来完成的。看看这个很好的答案了解详情。

已经开发了多个库来处理流 API 中的异常处理。例如,您可以查看 NoException 库:https ://noexception.machinezoo.com/

它为您提供了一种方便的方法来包装/潜行/记录/忽略已检查或未检查的异常。

例如,在您的情况下,它将是:

.map(value -> Exceptions.sneak().function(mapper::doMap))

或者

.map(value -> Exceptions.wrap().function(mapper::doMap))

PS:我不是图书馆的作者,也不是贡献者,但我在几个项目中使用过这个图书馆。


推荐阅读