捕获可抛出和处理特定异常

2022-09-01 19:59:01

好吧,我知道捕捉可投掷不是一个好主意:

    try {
         // Some code
    } catch(Throwable e) { // Not cool!
        // handle the exception
    }

但最近我正在阅读一个开源代码,我看到了这个有趣的(至少对我来说)代码:

    try {
        // Some Code
    } catch (Throwable ex){
        response = handleException(ex, resource);
    }

    private handleException(Throwable t, String resource) {
        if (t instanceof SQLEXception) {
               // Some code
        } else if (t instanceof IllegalArgumentException) {
               //some code
        } //so on and so forth
    }

这似乎不是那么糟糕?这种方法有什么问题?


答案 1

有各种各样的原因,为什么你不应该抓住一个可投掷的。首先,这包括 s - 如果出现其中之一,应用程序通常无能为力。此外,Throwable减少了你发现发生了什么的机会。你得到的只是“发生了不好的事情” - 这可能是一场灾难,或者只是一个麻烦。ThrowableError

另一个 aproach 更好,但当然我仍然不会捕获 Throwable,但如果可能的话,尝试捕获更具体的异常。否则,你就会抓住一切,然后试图弄清楚发生了什么坏事。您的示例可以写为...

try {
    ...
} catch (SQLEXception ex){
    response = ... ;
} catch (IllegalArgumentException ex){
    response = ...;
}

...这将减少块的数量(只需要,因为作者首先决定在一个大桶中捕获所有内容)。它实际上是这样,那么你没有太多选择,当然。if ( ... instanceof ... )throws Throwable


答案 2

当你说捕捉不是一个好主意时,你是对的。但是,您在问题中提供的代码并没有以邪恶的方式捕获,而是让我们稍后再讨论。现在,您在问题中提供的代码有几个优点:ThrowableThrowable

1. 可读性

如果仔细查看代码,您会注意到,即使 catch 块正在捕获 ,该方法也会检查引发的异常类型,并可能根据异常类型采取不同的操作。ThrowablehandleException

您的问题中提供的代码等同于说:

try {
    doSomething();
} catch (SQLEXception ex){
    response = handleException(resource);
} catch(IllegalArgumentException ex) {
    response = handleException(resource);
} catch(Throwable ex) {
    response = handleException(resource);
}

即使您只需要捕获 10 多个异常,此代码也很容易占用大量代码行,并且多捕获构造不会使代码更干净。您在问题中提供的代码只是将 委托给另一种方法,以使完成工作的实际方法更具可读性。catch

2. 可重用性

可以很容易地修改 handleRequest 方法的代码并将其放在实用程序类中,并在整个应用程序中访问以处理 s 和 s。您甚至可以将方法提取为两种方法;一个处理,一个处理并具有进一步委托调用这些方法的方法。ExceptionErrorprivateExceptionErrorhandleExceptionThrowable

3. 可维护性

如果您决定要更改在应用程序中记录 s 的方式,则必须在单个位置进行此更改,而不是访问每个类中引发 .SQLExceptionSQLException

那么,抓住一个坏主意吗?Throwable

您在问题中提供的代码实际上与单独捕获并不相同。下面的代码段是一个很大的禁忌:Throwable

try {
   doSomething();
} catch(Throwable e) {
    //log, rethrow or take some action
}

你应该抓住或尽可能远离链条。ThrowableExceptioncatch

最后但并非最不重要的一点是,请记住,您在问题中提供的代码是框架的代码,并且框架仍然可以从中恢复某些错误。请参阅何时捕获 java.lang.Error 以获取更好的解释。


推荐