java-多次或单次尝试捕获
我正在清理我的一些代码,但到了一个不确定的地方。
目前,在我的大多数方法中,我只有一个try catch块,并且最后处理一些单独的异常,但是我认为拥有更多try catch块对于维护而言会更好。 但是,在分解代码时,我到了为同一类型的异常编写多个块的地步。 我可以看到为每个部分编写一个块的好处,因为然后我可以提供更多有关失败原因的详细信息。
我的问题是...这样做有不利之处吗? 可能会出现性能问题或其他看不见的隐藏怪物吗?
另外,在一个方法中处理多个异常的首选方法是什么,是否有行业标准?
为了更好地说明我的观点,这里有一些伪代码
//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
}
12个解决方案
50 votes
我总是尝试降低嵌套级别,以提高可读性和可维护性。 如果您有n个try / catch块,每个块都处理相同类型的异常,为什么不重构可将异常抛出到方法中的代码……它看起来像:
try {
firstBatchOfTricky();
secondBatchOfTricky();
....
nthBatchOfTricky();
} catch (ItWentBoomException e) {
// recover from boom
} catch (ItWentBangException e) {
// recover from bang
}
这比具有多个try / catching更具可读性。 请注意,您的方法应本着自我记录代码的精神描述它们的作用。
由于您具有自己的异常类型,因此可以将所需的数据添加到异常中,以在catch块中执行不同的操作。 当您说“更具体的消息”时,您可以将异常与详细消息一起抛出; 您不需要多个捕获块。 如果您想根据异常的状态做截然不同的事情,只需创建更多的异常类型和catch块,但是只创建一个try块,如我的伪代码所示...
最后,如果您无法从异常中恢复,则不应使用catch块使代码混乱。 抛出运行时异常并使其冒泡。 (@tony在评论中提供了很好的建议)
hvgotcodes answered 2020-01-26T20:19:48Z
47 votes
这不是性能或个人喜好问题,而是功能和需求问题。
假设我写:
方案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引发异常,则doThingB仍将执行。 在方案2中,如果doThingA引发异常,则不会执行doThingB。 因此,问题不是哪个性能更好或者代码可读性更强,而是如果doThingA失败,是否仍应执行doThingB?
如果您真正想要的是第二种行为,但是您想要不同的消息告诉用户出了什么问题,那么您应该抛出不同的异常,或者将消息文本放入异常中,即
void doThingA() throws SomeException
{
... whatever code ...
if (theWorldIsAboutToEnd)
throw new SomeException("doThingA failed");
}
然后在catch子句中,不显示常量字符串,而是显示SomeException.toString或SomeException.getMessage。
Jay answered 2020-01-26T20:20:35Z
4 votes
如果可以用不同的方式处理异常(不同的错误消息等),那么分别捕获它们就可以了。
如果Exception类型不同,这并不意味着您必须具有单独的try块,则可以具有多个catch的一个try块。
jzd answered 2020-01-26T20:21:00Z
1 votes
我个人的喜好是一次尝试,可能有多个捕获块,也可能没有。 我的方法在可行的情况下往往足够小。 如果您的时间太长了,以至于无法实用,那么也许您需要考虑重构。
关于catch块的一件事:如果您的catch块打印或记录了堆栈跟踪并重新抛出,我想您最好在方法签名中的throws子句中添加异常,然后使其冒泡。
duffymo answered 2020-01-26T20:21:25Z
1 votes
我同意以上答案的普遍共识,即单个try-catch块更好。 但是,当您的方法足够长以至于无法解决这个问题时,可能太长了。 如果异常处理更加本地化,从中提取新方法可能会更容易。 不过,我认为您最好的选择可能是在原始方法中提取简单地引发异常并将异常处理留在原处的方法-理想情况下是在单个try-catch块中。
Carl Manaster answered 2020-01-26T20:21:46Z
1 votes
这完全取决于场景。 如果您做了很多引发安全异常的事情,并且以相同的方式处理该情况,则可以使用try块。
但是,在我看来,使用许多较小的try / catch块通常更好。 使用较大的try / catch类似于使用多个goto语句,只是您无法确定gotos的来源。
例如,在下面的内容中,您如何分辨哪个方法将进入异常1,哪个方法将进入异常2? 如果它是一个小块,那很好,但是一旦变大,它将变得非常不可读。
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){ [...] }
JasonG answered 2020-01-26T20:22:20Z
0 votes
很好的问题。 我要说的是,您应该使用一个try-catch块。 我的推理:如果您有理由将您的方法划分为多个try-catch块,则您可能应该考虑将您的方法重构为多个方法,每个方法都具有自己的单个try-catch块。
Bob Kaufman answered 2020-01-26T20:22:40Z
0 votes
我尽量避免重复代码。 因此,如果对某种类型的异常的响应相同,则捕获一次。
BigMac66 answered 2020-01-26T20:23:00Z
0 votes
我更喜欢单次尝试捕获块。 如果方法的长度增加很多,那么我更喜欢将方法分为模块化内部的多个内部方法。
同样,有时您也许可以重用这些内部方法。
我觉得这样维护起来更清晰,更好。
Swift-Tuttle answered 2020-01-26T20:23:29Z
0 votes
这取决于您的代码逻辑-您是否可以随时中断过程(计算或其他操作),或者可以/应该/需要/必须控制流程并回滚/通知/验证/在任何情况下异常指示异常状态 。
如果要实现简单的RSS客户端,则可以将所有与套接字相关的代码保存在一个块中。 但是,如果您正在编写bittorrent客户端,则将需要状态机和更多粒度的异常处理。
tomash answered 2020-01-26T20:23:54Z
0 votes
看起来很老的问题。 但是,我的回答将使它变得毫无意义,因为在最近几天,Java 7添加了新功能来添加多种感知和catch块。 这将消除大量代码,并且看起来非常有趣。 我碰到过这个链接,其中介绍了“尝试使用资源”的概念。
Krishna answered 2020-01-26T20:24:15Z
0 votes
为了安全起见,请始终对每个引发异常的语句使用单独的try catch块,因为如果将所有内容都写在一个try块中,则如果任何语句引发异常,则将不会执行下面编写的语句。
Deepak Vajpayee answered 2020-01-26T20:24:35Z