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

时间:2016-06-15 11:44:42

标签: java exception-handling checked-exceptions unchecked-exception

我被告知我应该考虑在我的代码中将未经检查的异常放在 Checked exception 上,而不仅仅是扩展RuntimeException 和我自己的一个。 现在,我确实理解了两者之间的区别,但仍然不明白我为什么要这样做?

如果我有这个方法标题,它会引发两种异常:

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

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

1 个答案:

答案 0 :(得分:3)

IOException是可以接受的。调用者无法确定filePath是否存在,并且在执行该方法时仍然存在,并且您的方法必须能够发出问题的信号。在这种情况下抛出IOException是常规异常,但如果您更喜欢运行时异常,可以将其包装在UncheckedIOException内。未经检查的IO异常将与已检查的IOException一样清晰。您将失去(或获取,取决于观点)的是,您不会强制来电者处理它。

另一方面,NoSuchAlgorithmException异常肯定会被包装到运行时异常中。如果您的方法使用的算法不存在,则调用者无法执行任何操作。如果发生异常,它显然是一个错误,并且应该通过运行时异常来发出错误信号。因此,编写自己的运行时异常,包装原始的NoSuchAlgorithmException(这样,如果你扔掉它就不会失去问题的根本原因),并且不要打扰你代码的所有调用者永远不会发生的异常。

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

  • AFAIK,没有新的Java API再使用已检查的异常。例如,请参阅java.time,它永远不会抛出已检查的异常,尽管旧的等效项(如DateFormat)会抛出已检查的异常
  • Java是唯一检查异常的语言。
  • 检查的异常不适合Java 8中引入的功能习惯用法(lambda表达式,流等):没有功能接口会抛出已检查的异常。

我认为现在可以安全地说,检查过的异常是一个有趣的想法,但事实证明这是个坏主意。你应该更喜欢unchecekd例外。

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

public static Optional<String> getFileMd5(String filePath) {
    try {
        // your original code
    }
    catch (IOException e) {
        throw new UncheckedIOException(e);
    }
    catch (NoSuchAlgorithmException e) {
        throw MyCustomCryptoException(e);
    }
}