为啥要尝试在已检查的异常上抛出未检查的异常? [复制]

Posted

技术标签:

【中文标题】为啥要尝试在已检查的异常上抛出未检查的异常? [复制]【英文标题】:Why one should try throw unchecked exception over checked exception? [duplicate]为什么要尝试在已检查的异常上抛出未检查的异常? [复制] 【发布时间】:2016-10-16 12:21:05 【问题描述】:

有人告诉我,我应该考虑在我的代码中将 Unchecked 异常 抛到 Checked 异常 之上,不仅如此,而且要扩展 RuntimeException强> 用我自己的。 现在,我明白了两者的区别,但还是不明白为什么要这么做?

如果我有这个抛出 2 种异常的方法头:

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

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

【问题讨论】:

"Here's the bottom line guideline: If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception." “我为什么要用一个(不太详细的)例外来替换它们?”你不应该。唯一可以替换它们的是Exception,这意味着您要告诉调用代码的人可能会引发任何异常,他们必须相应地处理所有异常.这就像一个返回Object的方法:任何东西都可以返回,所以你必须为任何事情做好准备。声明您抛出特定异常意味着他们只知道处理这些异常。 【参考方案1】:

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);
    

【讨论】:

以上是关于为啥要尝试在已检查的异常上抛出未检查的异常? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

glCreateShader 在 OSX 上抛出异常,为啥?

为啥不抛出异常的代码允许捕获已检查的异常?

为啥在这种情况下允许抛出已检查的异常类型?

Junit强制在方法调用上抛出异常

在wso2上抛出异常

为啥抛出异常比返回错误代码更好?