ktu*_*nho 100 java exception-handling throwable
赶上是不好的做法Throwable?
例如这样的事情:
try {
// Some code
} catch(Throwable e) {
// handle the exception
}
Run Code Online (Sandbox Code Playgroud)
这是一种不好的做法还是我们应该尽可能具体?
Bal*_*usC 92
你需要尽可能具体.否则不可预见的错误可能会以这种方式蔓延开来.
此外,还有Throwable封面Error,通常没有回报点.您不想捕获/处理它,您希望程序立即死亡,以便您可以正确地修复它.
Bra*_*ugh 36
这是一个坏主意.事实上,即使是捕捉Exception通常也是一个坏主意.我们来看一个例子:
try {
inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(Throwable e) {
inputNumber = 10; //Default, user did not enter valid number
}
Run Code Online (Sandbox Code Playgroud)
现在,假设getUserInput()阻塞了一段时间,另一个线程以最坏的方式阻止你的线程(它调用thread.stop()).你的catch块会遇到ThreadDeath错误.这太糟糕了.捕获该异常后代码的行为很大程度上是未定义的.
捕获异常会出现类似的问题.可能getUserInput()因InterruptException或尝试记录结果时出现权限被拒绝异常或其他各种故障而失败.你不知道出了什么问题,因为那样,你也不知道如何解决这个问题.
你有三个更好的选择:
1 - 准确捕获您知道如何处理的异常:
try {
inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(ParseException e) {
inputNumber = 10; //Default, user did not enter valid number
}
Run Code Online (Sandbox Code Playgroud)
2 - 重新抛出遇到的任何异常,并且不知道如何处理:
try {
doSomethingMysterious();
} catch(Exception e) {
log.error("Oh man, something bad and mysterious happened",e);
throw e;
}
Run Code Online (Sandbox Code Playgroud)
3 - 使用finally块,这样您就不必记住重新抛出:
Resources r = null;
try {
r = allocateSomeResources();
doSomething(r);
} finally {
if(r!=null) cleanUpResources(r);
}
Run Code Online (Sandbox Code Playgroud)
gaw*_*awi 19
另外请注意,当您捕获时Throwable,您还可以捕获InterruptedException哪些需要特殊处理.有关更多详细信息,请参阅处理InterruptedException.
如果您只想捕获未经检查的异常,则可能还会考虑此模式
try {
...
} catch (RuntimeException exception) {
//do something
} catch (Error error) {
//do something
}
Run Code Online (Sandbox Code Playgroud)
这样,当您修改代码并添加可以抛出已检查异常的方法调用时,编译器会提醒您,然后您可以决定如何处理此情况.
duf*_*ymo 13
如果你绝对不能从方法中获得异常气泡,这并不是一个坏习惯.
如果你真的无法处理异常,这是一个不好的做法.最好在方法签名中添加"throws",而不仅仅是catch和re-throw,或者更糟糕的是,将它包装在RuntimeException中并重新抛出.
And*_*man 13
直接来自Error类的javadoc(建议不要捕获这些):
* An <code>Error</code> is a subclass of <code>Throwable</code>
* that indicates serious problems that a reasonable application
* should not try to catch. Most such errors are abnormal conditions.
* The <code>ThreadDeath</code> error, though a "normal" condition,
* is also a subclass of <code>Error</code> because most applications
* should not try to catch it.
* A method is not required to declare in its <code>throws</code>
* clause any subclasses of <code>Error</code> that might be thrown
* during the execution of the method but not caught, since these
* errors are abnormal conditions that should never occur.
*
* @author Frank Yellin
* @version %I%, %G%
* @see java.lang.ThreadDeath
* @since JDK1.0
Run Code Online (Sandbox Code Playgroud)
如果你使用过度热情地抛出错误的库,有时候需要捕获Throwable,否则你的库可能会杀死你的应用程序.
但是,在这些情况下,最好只指定库引发的特定错误,而不是所有Throwables.
这取决于您的逻辑或更具体的选择/可能性.如果有任何特定的异常,您可以以有意义的方式做出反应,您可以先捕获它并执行此操作.
如果没有,并且您确定您将对所有异常和错误执行相同的操作(例如,使用错误消息退出),则捕获throwable不是问题.
通常第一种情况成立,你不会抓住扔掉的东西.但是仍有很多案例可以让它正常运行.
Throwable是所有类的基类,而不是可抛出的类(不仅仅是异常).如果你发现OutOfMemoryError或KernelError,你几乎无能为力(参见何时捕获java.lang.Error?)
捕获异常应该足够了.
虽然它被描述为一种非常糟糕的做法,但您有时会发现罕见的情况,它不仅有用而且是强制性的.这是两个例子.
在Web应用程序中,您必须向用户显示含义完整错误页面.此代码确保发生这种情况,因为它是try/catch围绕所有请求handeler(servlet,struts操作或任何控制器......)的一个大问题.
try{
//run the code which handles user request.
}catch(Throwable ex){
LOG.error("Exception was thrown: {}", ex);
//redirect request to a error page.
}
Run Code Online (Sandbox Code Playgroud)
}
再举一个例子,考虑一下你有一个为资金转账业务提供服务的服务类.此方法返回TransferReceiptif传输完成或NULL不能传输.
String FoundtransferService.doTransfer( fundtransferVO);
Run Code Online (Sandbox Code Playgroud)
现在成像您List从用户获得资金转移,您必须使用以上服务来完成所有这些.
for(FundTransferVO fundTransferVO : fundTransferVOList){
FoundtransferService.doTransfer( foundtransferVO);
}
Run Code Online (Sandbox Code Playgroud)
但是如果发生任何异常会发生什么?您不应该停止,因为一次转移可能是成功的而且可能不是,您应该继续通过所有用户List,并将结果显示给每次转移.所以你最终得到了这段代码.
for(FundTransferVO fundTransferVO : fundTransferVOList){
FoundtransferService.doTransfer( foundtransferVO);
}catch(Throwable ex){
LOG.error("The transfer for {} failed due the error {}", foundtransferVO, ex);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以浏览许多开源项目,看看它throwable是否真的被缓存和处理.例如,这里是搜索tomcat,struts2和primefaces:
https://github.com/apache/tomcat/search?utf8=%E2%9C%93&q=catch%28Throwable https://github.com/apache/struts/search?utf8=%E2%9C%93&q=catch %28Throwable https://github.com/primefaces/primefaces/search?utf8=%E2%9C%93&q=catch%28Throwable
这个问题有点含糊;您是在问“可以抓到吗Throwable”,还是“可以抓到一个Throwable而不做任何事”吗?这里的很多人都回答了后者,但这是一个附带问题;的99%的时间你不应该“消费”或放弃例外,无论你是赶上Throwable或IOException或什么的。
如果您传播异常,答案(就像对许多问题的答案一样)是“视情况而定”。这取决于您对异常所做的事情——为什么要捕获它。
为什么要捕获的一个很好的例子Throwable是,如果有任何错误,则提供某种清理。例如在 JDBC 中,如果在事务期间发生错误,您可能希望回滚事务:
try {
…
} catch(final Throwable throwable) {
connection.rollback();
throw throwable;
}
Run Code Online (Sandbox Code Playgroud)
请注意,异常不会被丢弃,而是会传播。
但是作为一般策略,Throwable因为您没有理由并且懒得查看正在抛出哪些特定异常而进行捕获是一种糟糕的形式和一个坏主意。