关于java:使用内部检查异常抛出运行时异常是不好的做法?

Is it bad practice to throw a runtime exception with an inner, checked exception?

本问题已经有最佳答案,请猛点这里访问。

这是不好的做法吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public String foo(File file) {
    StringBuilder sb = new StringBuilder();
    try(
            BufferedInputStream bis =
                    new BufferedInputStream(
                            new FileInputStream(file))
    ) {
        for(int c = bis.read(); c != -1; c = bis.read())
            sb.append((char) c);
    } catch (IOException e) {
        throw new UncheckedIOException(e);
    }
    return sb.toString();
}

假设无法从选中的异常中优雅地恢复。


这并不理想,但在某些情况下,没有其他解决方案。

foo(File file)是一个接口方法的实现,或者是一个超类方法的重写(它不声明检查的异常)时,这种方法变得很方便。这种情况迫使您在内部处理异常,或者将其包装为未检查的异常。

然而,问题是EDCOX1(1)的子类应该表示编程错误;另一方面,EDCOX1(4)不表示编程错误,因此将其封装在EDCOX1×1中以规避Java编译器的检查是错误的。


对于这种情况,Java运行时使用EDCOX1 0。

我认为,定义新类型的未检查异常并让它们从库中逃脱是一种糟糕的实践,因为它会导致泄漏的抽象。如果要将检查异常重新抛出为未检查异常,请在核心Java运行时找到合适的EDCOX1×1子类。


检查过的异常是有问题的——我听说它们最好被描述为"失败的实验"。

未选中的运行时异常是处理棘手情况的很好方法。例如,您通常有一个大型的高级线程,该线程预期将"永远"运行。该线程中(在不同方法中)可能有30个位置从数据库中读取或与其他不稳定的源交互。

如果该数据源失败,您总是希望以相同的方式处理它——重新连接,然后重新启动主循环。

这在高级线程中很容易处理,但是如果每个对象自己处理它,它会在整个项目中传播可怕的错误检查代码。

因此,答案是,如果在该级别上没有任何有用的功能,请随意将您的已签入未检查的运行时异常包装起来——我建议不要抛出已检查的异常,除非有调用方必须立即处理的事情(几乎从来没有这种情况——大多数问题都可以在更高的级别上处理)。

顺便说一下,我经常这样做,而且几乎从不使用新的异常——除非您有理由在更高的级别区分异常,否则您可以重用现有的异常。