多次或单次尝试抓住

我正在清理一些我的代码,我来到了一个点,我不知道哪条路线会更好。

目前,我的方法大部分都有一个try catch块,最后处理了一些单独的exception,但是我认为有更多的try catch块会更好。 然而,在分解代码的同时,我又到了一个为同一类exception写入多个块的地步。 我可以看到为每个部分编写一个块,因为我可以给出更具体的说明为什么失败。

我的问题是…这样做有缺点吗? 有没有性能问题或其他一些我没有看到的隐藏的怪物?

另外,在一个方法中处理多个exception的首选方法是什么,是否有行业标准?

为了更好地说明我的观点,这里有一些伪代码

//multiple try catch for same exception try { //some code here } catch (MyException e) { //specific error message here } try { //some different code here } catch (MyException e) { //more specific error message indicating a different issue } 

为了可读性和可维护性,我总是试图降低嵌套层次。 如果你有n个try / catch块,每个处理相同types的exception,为什么不重构可以抛出exception的代码呢?它看起来像这样:

 try { firstBatchOfTricky(); secondBatchOfTricky(); .... nthBatchOfTricky(); } catch (ItWentBoomException e) { // recover from boom } catch (ItWentBangException e) { // recover from bang } 

这是恕我直言,比多个尝试/捕获更可读。 请注意,你的方法应该描述自己logging代码的精神。

既然你有自己的exceptiontypes,你可以添加你需要的exception数据在catch块中做不同的事情。 当你说'更具体的消息',你可以抛出exception与详细的消息; 你不应该需要多个catch块。 如果你想根据exception的状态做很大的不同的事情,只需创build更多的exceptiontypes和捕获块,但只有一个try块,因为我的伪代码显示…

最后,如果你不能从exception中恢复,你不应该用catch块混乱代码。 抛出一个运行时exception,让它冒泡。 (在评论中来自@tony的好build议)

这不是性能或个人喜好问题:这是一个function和需求问题。

假设我写:

情况1:

 try { doThingA(); } catch (SomeException panic) { System.out.println("doThingA failed"); } try { doThingB(); } catch (SomeException panic) { System.out.println("doThingB failed"); } 

情景2:

 try { doThingA(); doThingB(); } catch (SomeException panic) { System.out.println("doThingA or doThingB failed"); } 

这两种情况不是等同的:他们做不同的事情。 在场景1中,如果doThingA抛出exception,doThingB仍然执行。 在情况2中,如果doThingA引发exception,则不执行doThingB。 所以问题不在于哪个能够提供更好的性能,哪些更具可读性的代码,而是如果doThingA失败,应该执行还是不执行?

如果你真正想要的是第二个行为,但是你希望不同的消息告诉用户出了什么问题,那么你应该抛出不同的exception,或者把消息的文本置于exception

 void doThingA() throws SomeException { ... whatever code ... if (theWorldIsAboutToEnd) throw new SomeException("doThingA failed"); } 

然后在catch子句中,不是显示一个常量string,而是显示SomeException.toString或SomeException.getMessage。

如果exception处理方式不同(不同的错误消息等),那么单独捕获exception就没有问题了。

如果exceptiontypes不同,那并不意味着你必须有单独的try块,你可以有一个try块多个catch。

我的个人喜好是一次尝试,可能有或可能没有多个catch块。 我的方法往往足够小,这是有道理的。 如果你的实践太长了,也许你需要考虑重构。

关于catch块的一件事情:如果你的catch块打印或者logging堆栈跟踪并重新抛出,我会说你最好把方法签名中的throws子句添加到exception中,让它冒泡。

我同意上述答案的普遍共识,即一个try-catch块更好。 然而,当你的方法足够长时间来看待这个问题的时候,这可能太长了。 如果exception处理更加本地化,​​从中提取新的方法可能会更容易。 尽pipe如此,我认为最好的方法是提取只抛出exception的方法,并保留原始方法中的exception处理,理想情况下在一个try-catch块中。

这完全取决于场景。 如果你做了一堆引发安全exception的东西,并以相同的方式处理这个场景,你可以使用try块。

不过,话虽如此,我认为使用许多较小的try / catch块通常更好。 使用一个大的try / catch就像使用几个goto语句,除非你不知道goto是从哪里来的。

例如在下面,你怎么知道哪个方法会去exception1,哪个去exception2呢? 如果它是一个小块就好,但一旦变大,就变得很难理解了。

 try{ doThing1(); doThing2(); doThing3(); doThing4(); doThing5(); doThing6(); doThing7(); doThing8(); doThing9(); } catch (Exception1 e){ } catch (Exception2 e){ } 

下面更清楚。

 try{ doThing1(); } catch (Exception1 e){ [...] } doThing2(); doThing3(); doThing4(); doThing5(); doThing6(); doThing7(); doThing8(); try{ doThing9(); } catch (Exception2 e){ [...] } 

很好的问题。 我要说,你应该使用一个try-catch块。 我的推理:如果你有理由将你的方法分成多个try-catch块,你应该考虑将你的方法重构成多个方法,每个方法都有自己的try-catch块。

我尽量避免重复代码。 所以如果对某种types的exception的响应是相同的,那就赶上一次。

我更喜欢单一的try-catch块。 如果方法的长度增长很多,那么我更喜欢将方法分成多个模块性的瞳孔的内部方法。
也有时你可能能够重新使用这些内部方法。
我觉得这样更干净,更好维护。

这取决于你的代码逻辑 – 你可以在任何时候中断你的进程(计算或其他),或者你可以/应该/必须/必须控制stream和回滚/通知/validation/ wulfverify如果某些错误情况在特定步骤。

如果您正在实现简单的RSS客户端,则可以将所有与套接字相关的代码保存在一个块中。 但是,如果你正在写BitTorrent客户端,你将需要状态机和更多的粒度exception处理。

这看起来很古老的问题。 但是,我的回答会使它更具有说服力,因为在最近的几天里,Java 7增加了新function来添加多个扩展和catch块。 这将消除大量的代码,看起来非常有趣。 我遇到了这个关于试用资源概念的链接。

为了安全起见,每个exception抛出语句都要使用单独的try catch块,因为如果在一个try块中全部写入,那么如果任何语句抛出一个exception,那么写在其下面的语句将不会被执行。