为什么“没有捕获的尝试”不满足异常处理的“处理或声明法”?

时间:2016-01-22 14:30:17

标签: java exception-handling

在Head First Java(第2版)一书的“第11章:危险行为”中,有人说“没有捕获的尝试不能满足处理或宣布法律”,并举了一个例子:

void go() throws fooException {
    try {
        x.doStuff();
    } finally {
        //something
    }
}

但是这个代码不能被解释为“躲避”,因为它会将异常抛出到调用它的方法而不处理问题吗?

3 个答案:

答案 0 :(得分:0)

一般情况下,如果你期望抛出一个异常,并且你不打算自己捕获并处理它,那么警告其他程序员你的方法应该抛出异常是很有礼貌的。如果异常在没有声明的情况下冒泡,那么当应用程序突然失败时,任何调用爆炸方法的人都会感到惊讶。找到这种选择的方法被认为是不好的做法。

话虽这么说,我几乎从未见过尝试/终于在实践中。一个更常见的编程错误是空的catch块,其中捕获并以静默方式丢弃异常。虽然try / finally块会明显地显示出来并且很快就会被测试,但是空的catch块会产生更多微妙的错误,因为程序不会通知任何人它正在破坏。

答案 1 :(得分:0)

看看Head First Java书(特别是“躲避(通过声明)”这一部分只会延迟不可避免的事情),你的样本符合他们对“躲避”的定义,但这并不意味着存在问题。他们指出的唯一问题是每个嵌套方法调用传播异常,包括main方法,以便JVM必须处理它。即使这样,如果你有一个无头批处理作业,你想要一些例外来终止作业(你可能通过从shell脚本调用java代码来记录它,将stderr重定向到一个文件,以便记录异常),这可能是很好,这取决于你需要做什么。这只是需要注意的事情。

异常的全部意义在于,当您遇到问题时,很多时候代码中的位置不是解决该问题的地方,而是需要将控制重新定位到调用堆栈中更高的位置。在许多情况下,最好的策略是创建一个全局异常处理程序,它接受从应用程序中许多不同级别抛出的异常(例如,在Web应用程序中,如果在许多情况下出现错误,最好的办法是终止请求,记录异常,并显示错误页面)。

在第一次抛出异常时立即处理异常确实相对不常见。让方法传递捕获异常没有错,让它从方法中抛出。这本书只是试图指出最终应该抓住它。

有一个可能存在的问题,需要注意的是finally块。在doStuff方法中说出错误导致异常被抛出。在出路的过程中,finally块被调用,如果从finally块抛出任何内容,那么该异常优先,并且从try块抛出的异常会丢失。这称为异常屏蔽。这很糟糕,因为通常由finally抛出的异常不是您想要看到的异常,try-block抛出的异常是信息性的。创建try-with-resources语句是为了通过在try块中抛出另一个异常时抑制关闭时抛出的异常来帮助解决这个问题。

答案 2 :(得分:-1)

你要么尝试一下try / catch块,要么添加一个投掷,而不是两者的混合。

void go() throws fooException { /* do something */ }

或者

void go() { try {} catch(FooException e) {} finally { /* do something */ }}