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

Nim*_*rod 7 java exception-handling checked-exceptions unchecked-exception

我被告知我应该考虑在我的代码中对Checked异常抛出Unchecked异常,而不仅仅是这样,而是用我自己的扩展RuntimeException.现在,我确实理解了两者之间的区别,但仍然不明白我为什么要这样做?

如果我有这个方法标题,抛出2种异常:

public static Optional<String> getFileMd5(String filePath) throws NoSuchAlgorithmException, IOException {}
Run Code Online (Sandbox Code Playgroud)

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

JB *_*zet 4

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

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

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

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

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

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

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