为什么应该尝试抛出未经检查的异常而不是已检查的异常?
Why one should try throw unchecked exception over checked exception?
我被告知我应该考虑在我的代码中抛出 未经检查的异常 而不是 已检查的异常 不仅如此,而且用我自己的扩展 RuntimeException。
现在明白了两者的区别,但还是不明白为什么要那样做?
如果我有这个抛出 2 种异常的方法头:
public static Optional<String> getFileMd5(String filePath) throws NoSuchAlgorithmException, IOException {}
为什么我应该用一个(不太详细的)例外替换它们?
IOException 是可以接受的。调用者无法确定 filePath 是否存在并且在执行该方法时仍将存在,并且您的方法必须能够发出问题信号。 IOException 是在这种情况下抛出的常规异常,但如果您更喜欢运行时异常,则可以将其包装在 UncheckedIOException 中。未经检查的 IO 异常与已检查的 IOException 一样清晰。您将失去(或获得,取决于观点)的是您不会强迫调用者处理它。
另一方面,NoSuchAlgorithmException 异常绝对应该包装到运行时异常中。如果您的方法使用不存在的算法,调用者将无法执行任何操作。如果发生该异常,则显然是一个错误,并且错误应该由运行时异常发出信号。因此,编写您自己的运行时异常,它包装原始的 NoSuchAlgorithmException(这样您就不会在抛出问题时丢失问题的根本原因),并且不要用一个应该异常的异常来打扰代码的所有调用者永远,永远不会发生。
关于运行时异常与检查异常,这主要是一个基于意见的问题,但有几点需要注意:
- AFAIK,新的 Java API 不再使用已检查的异常。例如,请参阅 java.time,它从不抛出已检查的异常,尽管旧的等效项(如 DateFormat)会抛出已检查的异常
- Java 是唯一具有检查异常的语言。
- 已检查的异常与Java 中引入的函数式习语(lambda 表达式、流等)不太吻合 8:没有函数接口会引发已检查的异常。
我认为现在可以肯定地说检查异常是一个有趣的想法,但事实证明这是一个糟糕的想法。你应该更喜欢 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);
}
}
我被告知我应该考虑在我的代码中抛出 未经检查的异常 而不是 已检查的异常 不仅如此,而且用我自己的扩展 RuntimeException。 现在明白了两者的区别,但还是不明白为什么要那样做?
如果我有这个抛出 2 种异常的方法头:
public static Optional<String> getFileMd5(String filePath) throws NoSuchAlgorithmException, IOException {}
为什么我应该用一个(不太详细的)例外替换它们?
IOException 是可以接受的。调用者无法确定 filePath 是否存在并且在执行该方法时仍将存在,并且您的方法必须能够发出问题信号。 IOException 是在这种情况下抛出的常规异常,但如果您更喜欢运行时异常,则可以将其包装在 UncheckedIOException 中。未经检查的 IO 异常与已检查的 IOException 一样清晰。您将失去(或获得,取决于观点)的是您不会强迫调用者处理它。
另一方面,NoSuchAlgorithmException 异常绝对应该包装到运行时异常中。如果您的方法使用不存在的算法,调用者将无法执行任何操作。如果发生该异常,则显然是一个错误,并且错误应该由运行时异常发出信号。因此,编写您自己的运行时异常,它包装原始的 NoSuchAlgorithmException(这样您就不会在抛出问题时丢失问题的根本原因),并且不要用一个应该异常的异常来打扰代码的所有调用者永远,永远不会发生。
关于运行时异常与检查异常,这主要是一个基于意见的问题,但有几点需要注意:
- AFAIK,新的 Java API 不再使用已检查的异常。例如,请参阅 java.time,它从不抛出已检查的异常,尽管旧的等效项(如 DateFormat)会抛出已检查的异常
- Java 是唯一具有检查异常的语言。
- 已检查的异常与Java 中引入的函数式习语(lambda 表达式、流等)不太吻合 8:没有函数接口会引发已检查的异常。
我认为现在可以肯定地说检查异常是一个有趣的想法,但事实证明这是一个糟糕的想法。你应该更喜欢 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);
}
}