5

假设这段代码在 20 个地方并且总是相同的

try {
    // do something
} catch (FirstException e) {
    // log it
} catch (SecondException e) {
    // log it
}

使用这样的东西不是更好还是instanceof不是好的解决方案?

try {
    // do something
} catch(Exception e) {
    logException(e);
}

void logException(Exception e) {
    if (e instanceof FirstException) {
        // log it
    } else if (e instanceof SecondException) {
        // log it differently
    } else {
        // do something with other exception 
    }
}

我真正讨厌解决方案的唯一一件事是捕捉Exception这绝对不是最好的方法......有没有更好的方法?

4

4 回答 4

9
  1. 在 Java 7 中,使用catch (FirstException1 | SecondException | ...)
  2. 可能没有什么问题catch (Exception e)——您确实想记录所有异常,不是吗?我实际上会建议catch (Throwable t),因为OutOfMemoryErrors 和StackOverflowErrors 也想被记录。

多年记录异常经验的建议是以相同的方式记录它们。异常消息作为人类可读的文本就足够了,开发人员真正需要调试的是堆栈跟踪。

请注意一件事:永远不要过早捕获异常:在整个应用程序的一个地方捕获它们,即所谓的异常屏障——它位于您进入和退出工作单元的级别。

如果检查的异常在较低级别给您带来麻烦,请将它们包装成RuntimeException

try {
  ...
} 
catch (RuntimeException e) {throw e;} 
catch (Exception e) {throw new RuntimeException(e);}

只有当您提前准确地知道存在对您的应用程序具有业务级别意义的异常,并且不会中止当前工作单元,而是重定向其流程时,才适合在较低级别捕获该异常。在实践中,与应用程序代码抛出的所有可能异常相比,此类异常很少见。

于 2013-03-21T08:50:45.620 回答
1

第一种方法肯定更好。通常,捕获是一种不好的做法,Exception因为在这种情况下,您RuntimeException也会捕获 s。

于 2013-03-21T08:50:19.507 回答
1

如果您只需要记录异常,前者是干净且很好的解决方案。

否则第一种方法更好。

于 2013-03-21T08:50:20.127 回答
1

在“Refactoring to Patterns”一书中,常见的重构之一是“用多态替换 instanceof”——换句话说,每当您使用 instanceof 时,请考虑多态实际上是否会更好地工作。. .

话虽如此,对于这个特定的问题,Spring 用运行时异常替换受检异常的哲学浮现在脑海中(请原谅双关语)。

这个想法是检查的异常可以被过度使用——异常是可以恢复的吗?如果是的话,好的。. . 如果没有,就让它向上传播。您可以通过以下方式做到这一点:

  • 重新抛出它。. . (但更好)
  • 将其包装在 RuntimeException 中

创建一个日志记录方面:

要考虑的另一件事是,如果您确实需要在这些异常发生时准确记录这些异常,而不是让它们在链上传播,并且它们发生在 20 个不同的地方,那么它们是一个横切关注点。. . 您可以让常规方法重新抛出异常,然后编写一个方面来捕获并记录它们。. . . 再次使用 Spring 使这变得容易。

于 2013-03-21T08:54:04.723 回答