java在捕获异常并弹窗_关于java:捕获抛出异常并处理特定异常

好吧,我知道捕捉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

}

这似乎没有那么糟糕吗? 这种方法有什么问题?

有时,尤其是在框架中,除了捕获Throwable之外,您别无选择。 在应用程序级代码中,这仍然不是一个好主意,除非您希望拥有某种"不得已的处理程序"。

您是否有指向相关开源代码的链接(例如GitHub上的源文件)? 我可以想到几个用例,根据实际情况,这可能是一个不错的策略。

@James_pic你去了github.com/Eldelshell/jongo/blob/master/jongo-core/src/main/

有多种原因导致您不应该使用Throwable。首先,Throwable包括Error s-如果其中之一出现,通常应用程序无能为力。而且Throwable减少了您发现已发生事件的机会。您得到的只是"一件坏事已经发生了"-这可能是灾难,也可能是令人讨厌的事情。

另一个方法更好,但是我当然不会捕获Throwable,但是如果可能的话,尝试捕获更具体的Exception。否则,您会抓住一切,然后尝试找出发生哪种不好的事情。您的示例可以写成...

try {

...

} catch (SQLEXception ex){

response = ... ;

} catch (IllegalArgumentException ex){

response = ...;

}

...这将减少if ( ... instanceof ... )块的数量(之所以需要,是因为作者首先决定将所有东西都放在一个大桶中)。实际上是throws Throwable的东西,那么您当然没有太多选择。

问题是有些Error很容易恢复。如果一个框架试图加载一个类而失败了,那仍然可以。

在这种情况下,框架不应产生错误,而应产生更有意义的异常。当然,事实并非总是如此。

不,我的意思是框架本身必须捕获错误并加以处理。不幸的是,Java的作者没有区分可恢复错误和不可恢复错误,因此有时(非常罕见)捕获Throwable是唯一明智的选择。

喔好吧。是的,您就在那里,但是对于非常低级的用例,这是非常非常特殊的情况。这就是为什么我写道"通常"应用程序不能做很多事情的原因。如果您是Spring框架并且遇到错误,则可能可以做些事情。如果您是HelloWorld应用程序,则最好的选择是在有人修复您的错误时放假;-)

@FlorianSchaetz如果您是Web服务器,并且在处理请求时遇到错误,则只想记录该请求并中止该请求,而无需关闭服务器。 (除非每个请求都引发错误)

说捕获Throwable不是一个好主意,这是对的。但是,您在问题中出现的代码并不是以一种邪恶的方式捕获Throwable,而是让我们稍后再讨论。现在,您在问题中呈现的代码具有几个优点:

1.可读性

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

您的问题中提供的代码与说:

try {

doSomething();

} catch (SQLEXception ex){

response = handleException(resource);

} catch(IllegalArgumentException ex) {

response = handleException(resource);

} catch(Throwable ex) {

response = handleException(resource);

}

即使您只需要捕获10个以上的异常,该代码也很容易占用很多代码行,并且multi-catch构造不会使代码更清晰。您在问题中出现的代码只是将catch委派给另一个方法,以使执行工作的实际方法更具可读性。

2.可重用性

handleRequest方法的代码可以轻松地修改并放置在实用程序类中,并在整个应用程序中进行访问以处理Exception和Error。您甚至可以将方法提取到两个private方法中。一个处理Exception的对象和一个处理Error并具有handleException方法的对象,该方法采用Throwable进一步将调用委托给这些方法。

3.可维护性

如果您决定要更改在应用程序中记录SQLException的方式,则必须在单个位置进行此更改,而不是访问每个抛出SQLException的类中的每个方法。

那么赶上Throwable是个坏主意吗?

您在问题中出现的代码与仅捕获Throwable并不完全相同。以下代码很重要:

try {

doSomething();

} catch(Throwable e) {

//log, rethrow or take some action

}

您应该在catch链中尽可能远地捕获Throwable或Exception。

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

为什么要使用Throwable而不是仅仅使用Exception?该方法必须称为handleThrowable ...

@maraca请记住,这是框架代码。 Fameworks希望捕获可恢复的错误。 (链接错误是一个很好的例子)。话虽如此,我同意他们在这里使用的方法名称并不是一个很好的选择,但这与实际问题无关。

谢谢,我明白了。但是我认为这是一个设计问题,无法提出一种可能是一种不错的方法的方案。与其捕获所有内容并调用此方法,不如直接在正确的位置使用throws和handle。

@maraca他们捕获的大多数异常都是RuntimeException的子类。 RuntimeException不需要遵循catch或指定要求,因此框架专家无法保证其API的用户将处理这些异常。他们可能将这些异常包装到已检查的异常中并抛出它们,或者他们可能代表他们处理这些异常。底线,在这种情况下为IMO,没有必要声明方法throws RuntimeException。

懒惰地捕获Throwable是个坏主意。

在引入try-multi-catch之前,这尤其诱人。

try {

...

} catch (SomeException e) {

//do something

} catch (OtherException e) {

//do the same thing

} ...

重复捕获块是乏味且冗长的,因此有些人决定只捕获Exception或Throwable并加以处理。应当避免这种情况,因为:

这使您很难按照自己的意愿去做。

您可能最终会遇到很多无法处理的东西。

如果您完全吞下catch块中的Throwable,则应受到加分处罚。 (而且我们都已经看到了执行此操作的代码... :))

但是在绝对必要时捕获Throwable是可以的。

什么时候有必要?非常稀有。在框架样式的代码中,有多种情况(动态加载外部类是最明显的一种情况),在独立应用程序中,一个典型的示例是尝试在退出之前显示/记录某种错误消息。 (请记住,该尝试可能会失败,因此您不想在此放置任何关键内容。)

根据经验,如果您对异常/错误无能为力,则根本不应该抓住它。

使用庞大的网络确实有两种有效用法:

如果您将统一处理所有事情,例如用于记录/报告的顶级捕获,则可能紧随其后退出。

为了减少重复,可以将所有处理导出到自己的方法中。

抓住那里最衍生的共同祖先,以避免额外的工作并增加清晰度。

DRY是重要的设计原则。

在这两种情况下,除非您期望该异常并完全处理它,否则都将其重新抛出。

您发布了指向Jongo的链接,该链接演示了此技术的一种可能用法:重用错误处理代码。

假设您有一大堆错误处理代码,这些代码自然会在代码中的各个位置重复其自身,例如Jongo对某些标准错误类别产生标准响应。将错误处理代码提取到方法中可能是一个好主意,因此您可以在所有需要的地方重复使用它。

但是,这并不是说Jongo的代码没有错。

捕获Throwable(而不是使用multicatch)仍然令人怀疑,因为您可能会捕获到您实际上没有能力处理的Error(您确定要捕获ThreadDeath吗?)。在这种情况下,如果您绝对必须捕获Throwable,最好"捕获并释放"(即,扔掉所有您不想捕获的东西)。 Jongo不会这样做。

只是为了提供平衡-在一个地方我总是catch (Throwable):

public static void main(String args[]) {

try {

new Test().test();

} catch (Throwable t) {

t.printStackTrace(System.err);

}

}

至少某些地方显示出某些地方出了问题。

真???我从不做...因为它总是会被打印出来。也许是特定于操作系统的?

Java 7解决了一些烦人的问题,即以相似的处理方式多次捕获相似的异常。您绝对不应该做这个人在这里所做的事情。只要捕获所需的适当异常,它看起来就很丑陋,但这就是throws的用途,将其传递给应该捕获它的方法,并且您不应该浪费太多的代码空间。

查看此链接以获取更多信息。

首先,捕获Throwable使您的应用程序变得不透明。您应该在捕获异常方面尽可能地明确,以在特殊情况下实现良好的可追溯性。

让我们看一下handleException(...)方法,看看这种方法会发生的一些问题:

您捕获了Throwable但仅处理异常,如果发生异常,例如错误类型为OutOfMemoryError抛出? -我看到坏事发生了...

关于使用instanceof进行良好的面向对象编程,会破坏Open-Closed-Principle,并使代码更改(例如,添加新的异常)变得非常混乱。

从我的角度来看,catch块是为在handleExceptions(...)中试图涵盖的功能而专门制造的,因此请使用它们。

您始终可以捕获不同类型的异常,并根据所获取的异常类型执行某些操作。

这是一个例子

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.

}

你可能感兴趣的:(java在捕获异常并弹窗)