修改了异常处理最佳实践

时间:2011-03-11 15:15:41

标签: java exception exception-handling

我有一段代码,我捕获所有异常并在最后抛出一个通用异常。像这样:

try {
  // do something here
} catch (Whatever e) {
  throw new MyException(e.getMessage());
}

这种方式使我的函数定义看起来很干净,即“myFunc抛出MyException”但同时我失去了导致问题的语义。另一方面,如果我只抛出所有异常,那将使函数体更清晰,但函数的定义将包含1-5个throw语句。

我的问题是:什么更好?...我应该捕获所有异常,保持函数定义清洁,还是应该抛出一切保持函数体干净?

注意:第二种方法也会使我的函数的异常处理代码更加困难......

5 个答案:

答案 0 :(得分:4)

这通常是判断。你的函数应该暴露与它所在的层相关的异常。通常这意味着通过你调用的东西引发的异常,有时它不会。

例如,如果您有一个getAThingy函数,并且您的应用程序可以配置为有问题的东西可以来自数据库或文件,那么getAThingy可能不适合数据库中的SqlException,因为然后调用它的代码必须处理为文件或数据库配置的代码。 (它将成为一个漏洞抽象。)所以这就是你应该抓住并抛出其他更合适的东西的一个例子。

相反,如果您接受某种不应该null且有人通过null的标识符,那么在没有包装的情况下愉快地传递NullPointerException似乎是完全合适的它

答案 1 :(得分:4)

抛出10种不同类型的异常的函数没有任何问题,只要每个异常在上下文中都有意义。

如果你只是想发现出现问题,但你不需要确切知道什么,你可以坚持你的做法(即只抛出一个例外)。

另一方面,如果你需要对不同的问题作出反应,你应该保留原来的例外。

没有“更好”的方法,这取决于你需要在上层的上下文和信息。你不应该担心保持身体或功能原型“干净”,两种解决方案都是“干净”。唯一重要的决定因素是需要信息。

答案 2 :(得分:3)

为什么选择其中一个?

try { /* doing useful work */ }
catch (Whatever t) { throw new MyException(t); }

其中MyException的构造函数将Throwable作为参数。

总的来说,我同意Krtek和T.J.克劳德说过;抛出在你正在使用的抽象层次上有意义的异常,无论这意味着你列出了一种类型的异常,还是十种。

答案 3 :(得分:0)

我听到的关于异常的建议是将它们尽可能地靠近它们被抛出的地方处理。因此,例如,如果您可以从异常中恢复,请在抛出异常的方法中执行此操作,并且根本不会触发异常。如果您无法从异常中恢复,但代码层或几层可以,请考虑推广它。还要考虑返回一个值,该值只表示调用代码需要修复的内容。

如果无法从调用层次结构中某个适当位置的所有代码恢复异常,则需要将其转换为用户友好的错误消息,理想情况下警告用户修复异常并重新运行任务的方法甚至在发生错误的地方重新启动任务。

最后,每当你包装一个异常,并且有时你可能想要包装一个异常时,将整个异常包装为源,这样你就可以有很好的嵌套异常。

答案 4 :(得分:0)

如果你看一下异常类的Javadoc,你会发现它可能需要一个Throwable。这实际上取决于你正在做什么,但更多的时候我选择通过做类似的事情保留堆栈跟踪:

catch(SomeException ex) {
    throw new ClearerException("This is what specifically went wrong", ex);
}

通过这种方式,您可以获得可以放入的好消息,但是如果您想深入研究并找到原因,那么堆栈跟踪也是如此。