繁体   English   中英

修订了异常处理最佳实践

[英]Exception handling best practices revised

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

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

这种使我的函数定义看起来很干净,即“ myFunc throws MyException”,但与此同时,我也失去了引起问题的原因的语义。 另一方面,如果我仅抛出所有异常,则将使函数主体更清晰,但函数的定义将包含1-5个throw语句。

我的问题是:什么更好?...我应该捕获所有异常,使函数定义保持整洁,还是应该扔掉所有东西以使函数主体保持整洁?

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

通常这是一个判断电话。 您的函数应该公开与其所在层相关的异常。通常,这意味着传递由您调用的事物引发的异常,有时却不这样做。

举例来说,如果你有一个getAThingy功能和应用程序可以被配置成问题的啄可以来自数据库或文件,它可能不适合getAThingy提高SqlException数据库中的情况下,因为那时的代码调用它必须处理该问题,无论是配置文件还是数据库。 (这将成为一个泄漏的抽象 。)因此,这是一个示例,说明您何时应该捕获并抛出其他更合适的东西。

相反,如果您接受某种不应该为null的标识符,并且有人传入null ,那么很高兴地传递NullPointerException而不包装它似乎是完全合适的。

只要每个异常在上下文中有意义,函数就可以抛出10种不同的异常。

如果您只是想检测出出了什么问题,而又不需要确切知道什么,则可以坚持使用您的方法(即仅引发一个异常)。

另一方面,如果您需要对不同的问题做出反应,则应保留原始异常。

没有“更好”的方法,这取决于上下文和您在上级需要的信息。 而且您不必担心保持主体或功能原型“干净”,这两种解决方案都是“干净的”。 唯一重要的决策因素是信息需求。

为什么选择一个?

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

其中MyException具有一个将Throwable作为参数的Throwable函数。

总的来说,我同意Krtek和TJ Crowder所说的话。 抛出在您正在使用的抽象级别有意义的异常,无论这意味着您列出一种类型的异常,还是列出十种类型的异常。

我所听到的关于异常的建议是将异常处理到尽可能接近它们被抛出的地方。 因此,例如,如果您可以从异常中恢复,请在引发该异常的方法中进行操作,而根本不要传播该异常。 如果您无法从异常中恢复,但是可以编写一个代码层或几层代码,请考虑对它进行处理。 还可以考虑返回一个仅指示调用代码需要修复的值。

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

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

如果您查看异常类的Javadoc,您会发现它可以采用Throwable。 这实际上取决于您在做什么,但是我经常选择通过以下操作来保留堆栈跟踪:

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

这样一来,您就可以从可以发送的好消息中获益,但是如果您想更深入地研究并找到原因,堆栈跟踪也就在那里。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM