好的,我知道抓住throwable不是一个好主意:
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
}
这似乎不是那么糟糕?这种方法有什么问题?
答案 0 :(得分:19)
你有多种原因不应该抓住Throwable。首先,Throwable
包括Error
s - 如果其中一个出现,应用程序通常不会做多少。此外,Throwable减少了发现的可能性,发生了什么。你得到的只是"发生了一些不好的事情" - 这可能是一场灾难,也可能只是一种滋扰。
另一个方法更好但当然我仍然不会抓住Throwable,但是如果可能的话,尽量抓住更具体的异常。否则你会抓住所有东西,然后尝试找出发生了哪种坏事。你的例子可以写成......
try {
...
} catch (SQLEXception ex){
response = ... ;
} catch (IllegalArgumentException ex){
response = ...;
}
...这会减少if ( ... instanceof ... )
块的数量(只需要因为作者首先决定在一个大桶中捕获所有内容而需要)。它实际上是throws Throwable
,当然,你没有多少选择。
答案 1 :(得分:18)
当你说抓住var routerApp = angular.module('routerApp', ['ui.router','ngResource']);
routerApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
// HOME STATES AND NESTED VIEWS
.state('partyDetail', {
url: '/party/:partyID',
不是一个好主意时,你是对的。但是,您在问题中提供的代码并没有以邪恶的方式捕捉Throwable
,而是让我们稍后再讨论。目前,您在问题中提供的代码有几个优点:
<强> 1。可读性强>
如果仔细查看代码,您会注意到即使catch块正在捕获Throwable
,Throwable
方法也会检查抛出的异常类型,并可能采取不同的操作异常类型。
您问题中提供的代码与以下内容同义:
handleException
即使你只需要捕获10多个例外,这段代码很容易占用大量的代码,而multi-catch构造也不会让代码更清晰。您在问题中提供的代码只是将try {
doSomething();
} catch (SQLEXception ex){
response = handleException(resource);
} catch(IllegalArgumentException ex) {
response = handleException(resource);
} catch(Throwable ex) {
response = handleException(resource);
}
委托给另一个方法,以使实际工作方法更具可读性。
<强> 2。可重用性强>
handleRequest方法的代码可以轻松修改并放在实用程序类中,并在整个应用程序中访问,以处理catch
和Exception
。您甚至可以将方法提取为两个Error
方法;一个处理private
和一个处理Exception
并使用Error
方法进行handleException
进一步委托调用这些方法的方法。
第3。 Maintainibility 强>
如果您决定要更改在应用程序中记录Throwable
的方式,则必须在单个位置进行此更改,而不是访问每个抛出{{1}的类中的每个方法}}
所以抓住SQLException
一个坏主意?
您在问题中提供的代码与单独捕获SQLException
的代码并不完全相同。以下代码是一个很大的禁忌:
Throwable
您应该尽可能远离Throwable
链中的try {
doSomething();
} catch(Throwable e) {
//log, rethrow or take some action
}
或Throwable
。
最后但并非最不重要,请记住,您在问题中提供的代码是框架代码,并且框架仍然可以从中恢复某些错误。有关更好的解释,请参阅When to catch java.lang.Error。
答案 2 :(得分:9)
抓住Throwable
出于懒惰是一个坏主意。
在try-multi-catch
被引入之前,这是特别诱人的。
try {
...
} catch (SomeException e) {
//do something
} catch (OtherException e) {
//do the same thing
} ...
重复捕获块是繁琐冗长的,所以有些人决定只抓住Exception
或Throwable
并完成它。这是应该避免的,因为:
Throwable
,你应该受到奖励惩罚。 (而且我们都看到了代码那样......:)) 但是在绝对必要时抓住Throwable
就可以了。
什么时候需要?非常稀有。在框架式代码中有各种场景(动态加载外部类是最明显的一种),在独立应用程序中,典型的例子是在退出之前尝试显示/记录某种错误消息。 (请记住,尝试可能会失败,所以你不想在那里放任何关键的东西。)
根据经验,如果您无法对异常/错误采取任何措施,则根本不应该抓住它。
答案 3 :(得分:3)
您发布了一个指向Jongo的链接,该链接演示了此技术的一种可能用途:重新使用错误处理代码。
假设您有一大块错误处理代码,它们会在代码中的不同位置自然重复 - 例如Jongo会为某些标准类错误生成标准响应。将错误处理代码提取到方法中可能是个好主意,因此您可以从所需的所有位置重复使用它。
然而,这并不是说Jongo的代码没有任何问题。
抓住Throwable
(而不是使用群集)仍然存在疑问,因为您可能会抓住Error
您无法正常处理的事情(您是否确定?) 你打算抓住ThreadDeath
?)。在这种情况下,如果你必须抓住Throwable
,最好“捕捉和释放”(即重新抛出任何你不想抓住的东西)。 Jongo没有这样做。
答案 4 :(得分:3)
使用庞大网络有两个有效用途:
如果您将统一处理所有内容,例如用于记录/报告的顶级捕获,可能会立即退出。
通过将所有处理导出到自己的方法来减少重复 抓住最衍生的共同祖先,以避免额外的工作,提高清晰度 Here is a directory with images of each project's properties screens and workspace:是一项重要的设计原则。
在这两种情况下,除非您预期该异常并完全处理,否则请重新抛出。
答案 5 :(得分:2)
首先,捕获Throwable会使您的应用程序变得不透明。在特殊情况下,您应该尽可能明确地捕获异常以实现良好的可追溯性。
让我们看看方法handleException(...),看看这种方法出现的一些问题:
从我的角度来看,catch-blocks正是针对handleExceptions(...)中试图覆盖的功能而设计的,所以请使用它们。
答案 6 :(得分:2)
Java 7解决了一些繁琐的问题,这些繁琐程序具有类似处理的类似异常。你绝对不应该做这个人在这里所做的事情。只是根据需要捕获适当的异常,它可能看起来很难看,但那就是throws
的用途,将它传递给应该捕获它的方法,你不应该浪费太多的代码空间
答案 7 :(得分:2)
只是为了提供平衡 - 有一个的地方,我将永远catch (Throwable)
:
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
至少有些东西显示某些地方出了问题。
答案 8 :(得分:0)
您可以随时捕获不同类型的异常,并根据您获得的异常类型执行某些操作。
这是一个例子
try{
//do something that could throw an exception
}catch (ConnectException e) {
//do something related to connection
} catch (InvalidAttributeValueException e) {
// do anything related to invalid attribute exception
} catch (NullPointerException e) {
// do something if a null if obtained
}
catch (Exception e) {
// any other exception that is not handled can be catch here, handle it here
}
finally{
//perform the final operatin like closing the connections etc.
}