Java 为什么“a”;“不抓不抓”;不满足;处理或宣布法律”;异常处理的定义?

Java 为什么“a”;“不抓不抓”;不满足;处理或宣布法律”;异常处理的定义?,java,exception-handling,Java,Exception Handling,在《第一代Java》(第二版)一书的“第11章:风险行为”中,有这样一句话:“没有捕获的尝试不符合句柄或声明法则”,并给出了一个例子: void go() throws fooException { try { x.doStuff(); } finally { //something } } 但是,如果该代码在不处理问题的情况下向调用它的任何方法抛出异常,那么该代码难道不能被解释为“回避”吗?您要么执行try/catch块,要么添加抛出,

在《第一代Java》(第二版)一书的“第11章:风险行为”中,有这样一句话:“没有捕获的尝试不符合句柄或声明法则”,并给出了一个例子:

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

但是,如果该代码在不处理问题的情况下向调用它的任何方法抛出异常,那么该代码难道不能被解释为“回避”吗?

您要么执行try/catch块,要么添加抛出,而不是两者的混合

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


通常,如果您希望抛出异常,而您不打算自己捕获并处理它,那么有礼貌地警告其他程序员您的方法将抛出异常。如果在没有声明的情况下出现异常,那么调用爆炸方法的人会在应用程序突然失败时感到惊讶。在这个选择周围寻找方法被认为是不好的做法


话虽如此,我几乎从未在实践中见过try/finally。一个更常见的编程错误是空的catch块,在该块中捕获异常并无声地丢弃。虽然try/finally块会明显地表现出来,并在测试中很快被捕获,但空的catch块会产生更微妙的错误,因为程序不会通知任何人它正在崩溃。

查看第一本Java书的开头(特别是“回避(通过声明)只会延迟不可避免的事情”),你的样本符合他们对“躲闪”的定义,但这并不意味着有问题。他们指出的唯一问题是,每个嵌套方法调用都会传播一个异常,包括主方法,因此JVM必须处理它。即使如此,如果您有一个无头批处理作业,其中希望有一些异常终止该作业(并且您可以通过调用shell脚本中的java代码来记录该作业,该脚本将stderr重定向到一个文件,以便记录异常),这也可以,这取决于您需要做什么。这只是需要注意的事情

异常的全部要点是,当您经常遇到问题时,代码中的位置不是解决该问题的位置,相反,您需要将控制重新定位到调用堆栈中更高的位置。在许多情况下,最好的策略是创建一个全局异常处理程序,该处理程序接收应用程序中许多不同级别抛出的异常(例如,在web应用程序中,如果在许多情况下出现错误,最好的做法是终止请求、记录异常并显示错误页)

在第一次抛出异常的地方立即处理异常是非常不寻常的。让方法在捕获异常时传递,让它从方法中抛出,这没有什么错。这本书只是试图指出,最终会有什么东西抓住它


finally块可能存在需要注意的问题。假设doStuff方法出错,导致抛出异常。在退出的过程中,调用finally块,如果finally块抛出任何异常,那么该异常将优先,而try块抛出的异常将丢失。这称为异常屏蔽。这很糟糕,因为finally抛出的异常通常不是您希望看到的异常,try块抛出的异常是提供信息的异常。创建该语句是为了帮助处理此问题,方法是在从try块抛出另一个异常时,抑制close时抛出的异常

实际上,有一个很好的理由可以在抛出异常的方法中使用try finally而不使用catch,这就是即使您无法处理异常,您可能仍然需要对抛出的异常做出反应,例如,
try{stuff}finally{clean stuff}
。我不确定您的确切意思,但这肯定是一件合法的事情,而不是“现在这是别人的问题”之类的事情。如果在这里必须做一些事情,即使是在失败的情况下,那么它属于finally块。如果这里不能处理失败,那么调用方法应该知道这些失败。这是什么“处理或声明法则”。没有其他问题,所以请提及。见,谢谢!你的回答很有启发性!有趣。我不知道可以创建一个空的catch块。谢谢如果我的回答能回答你的问题,你能投赞成票或接受吗?
void go() { try {} catch(FooException e) {} finally { /* do something */ }}