多次或单次尝试捕获

Sha*_*ded 52 java coding-style exception-handling

我正在努力清理我的一些代码,然后我发现我不确定哪条路线会更好.

目前我在我的大多数方法上都有一个try catch块,它最后处理了一些单独的异常,但我认为有更多尝试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
}
Run Code Online (Sandbox Code Playgroud)

hvg*_*des 51

我总是尝试降低嵌套级别以提高可读性和可维护性.如果你有n个try/catch块,每个块处理相同类型的异常,为什么不重构可以将异常抛出到方法中的代码...它看起来像:

try {
    firstBatchOfTricky();
    secondBatchOfTricky();
    ....
    nthBatchOfTricky();
} catch (ItWentBoomException e) {
   // recover from boom
} catch (ItWentBangException e) {
   // recover from bang
}
Run Code Online (Sandbox Code Playgroud)

这比具有多个try/catches更具可读性.请注意,您的方法应该根据自我记录代码的精神描述它们的作用.

由于您有自己的异常类型,因此可以将异常所需的数据添加到catch块中以执行不同的操作.当您说"更具体的消息"时,您可以使用详细消息抛出异常; 你不应该需要多个catch块.如果你想根据异常的状态做出截然不同的事情,只需创建更多的异常类型并捕获块,但只有一个try块,因为我的伪代码显示...

最后,如果无法从异常中恢复,则不应该使用catch块使代码混乱.抛出运行时异常并让它冒泡.(@tony在评论中提出的好建议)


Jay*_*Jay 48

这不是性能或个人偏好问题:这是一个功能和需求问题.

假设我写道:

场景1:

try
{
  doThingA();
}
catch (SomeException panic)
{
  System.out.println("doThingA failed");
}
try
{
  doThingB();
}
catch (SomeException panic)
{
  System.out.println("doThingB failed");
}
Run Code Online (Sandbox Code Playgroud)

场景2:

try
{
  doThingA();
  doThingB();
}
catch (SomeException panic)
{
  System.out.println("doThingA or doThingB failed");
}
Run Code Online (Sandbox Code Playgroud)

这两种情况不等同:它们做不同的事情.在场景1中,如果doThingA抛出异常,则doThingB仍会执行.在场景2中,如果doThingA抛出异常,则不执行doThingB.所以问题不是哪个能提供更好的性能,哪个是更易读的代码,而是如果doThingA失败,那么仍然应该执行ThingB吗?

如果您真正想要的是第二种行为,但是您希望不同的消息告诉用户出了什么问题,那么您应该抛出不同的异常,或者将消息的文本放入异常中,即

void doThingA() throws SomeException
{
  ... whatever code ...
  if (theWorldIsAboutToEnd)
    throw new SomeException("doThingA failed");
}
Run Code Online (Sandbox Code Playgroud)

然后在catch子句中,不显示常量字符串,而是显示SomeException.toString或SomeException.getMessage.

  • 完美的,事实上我正在寻找这两种方案来解决 (5认同)
  • 此答案应标记为解决方案,因为它清楚地回答了问题。 (2认同)