关于java:为什么应该尝试在已检查的异常上抛出未经检查的异常?

Why one should try throw unchecked exception over checked exception?

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

有人告诉我,我应该考虑在代码中对检查过的异常抛出未检查过的异常,不仅如此,还应该用我自己的异常来扩展runtimeexception。现在,我确实明白这两者之间的区别,但仍然不明白我为什么要这样做?

如果我有这个方法头,它抛出两种异常:

1
public static Optional<String> getFileMd5(String filePath) throws NoSuchAlgorithmException, IOException {}

为什么我要用一个(不太详细的)异常来替换它们?


IOException是可接受的。调用方无法确定文件路径是否存在,并且在执行该方法时文件路径是否仍然存在,并且您的方法必须能够向问题发出信号。IOException是在这种情况下抛出的常规异常,但是如果您喜欢运行时异常,可以将其包装在一个未选中的EdioException中。未选中的IO异常将与选中的IOException一样清楚。你会失去(或获得,取决于你的观点)的是,你不会强迫来电者处理它。

另一方面,nosuchalgorithmexception异常应该被包装成运行时异常。如果您的方法使用的算法不存在,则调用方将无法执行任何操作。如果发生异常,这显然是一个bug,并且bug应该由运行时异常发出信号。因此,编写自己的运行时异常,它包装了原始的NoSuchalgorithmException(这样,如果您抛出它,就不会丢失问题的根本原因),也不会让代码的所有调用者都感到困扰,除非永远不会发生异常。

关于运行时异常和检查异常,这主要是一个基于意见的问题,但也应注意以下几点:

  • AFEK,没有新的Java API使用已检查的异常。例如,请参见java.time,它从不抛出检查异常,尽管旧的等效(如dateformat)抛出检查异常
  • Java是唯一有检查异常的语言。
  • 检查异常不符合Java 8中介绍的函数式习语(lambda表达式、流等):没有功能接口抛出检查异常。

我认为现在可以肯定地说,检查异常是一个有趣的想法,但事实证明这是一个糟糕的想法。您应该更喜欢unceckekd例外。

现在,如果您的问题是:如何抛出未检查的异常而不是检查的异常,那么很简单:

1
2
3
4
5
6
7
8
9
10
11
public static Optional<String> getFileMd5(String filePath) {
    try {
        // your original code
    }
    catch (IOException e) {
        throw new UncheckedIOException(e);
    }
    catch (NoSuchAlgorithmException e) {
        throw MyCustomCryptoException(e);
    }
}