Java 修订异常处理最佳实践
我有一段代码,捕获所有异常,并在最后抛出一个通用异常。大概是这样的:Java 修订异常处理最佳实践,java,exception,exception-handling,Java,Exception,Exception Handling,我有一段代码,捕获所有异常,并在最后抛出一个通用异常。大概是这样的: try { // do something here } catch (Whatever e) { throw new MyException(e.getMessage()); } 这使得我的函数定义看起来很清晰,即“myFunc抛出MyException”,但同时我失去了导致问题的语义。另一方面,如果我只是抛出所有异常,这将使函数体更干净,但函数的定义将包含1-5个抛出语句 我的问题是:什么更好?。。。我应该捕获所
try {
// do something here
} catch (Whatever e) {
throw new MyException(e.getMessage());
}
这使得我的函数定义看起来很清晰,即“myFunc抛出MyException”,但同时我失去了导致问题的语义。另一方面,如果我只是抛出所有异常,这将使函数体更干净,但函数的定义将包含1-5个抛出语句
我的问题是:什么更好?。。。我应该捕获所有异常,保持函数定义干净,还是应该抛出所有异常,保持函数体干净
注意:第二种方法也会使我的函数的异常处理代码变得更加困难…这通常是一个判断调用。您的函数应该公开与其所在层相关的异常。通常这意味着要通过你所呼叫的事物所引发的事件,有时则不然 例如,如果您有一个
getAThingy
函数,并且您的应用程序可以进行配置,使所讨论的内容可以来自数据库或文件,那么在数据库情况下,getAThingy
可能不适合引发SqlException
,因为无论是为文件还是数据库配置,调用它的代码都必须处理这个问题。(这将成为一个漏洞百出的抽象。)因此,这将是一个例子,说明您可能应该捕捉并抛出其他更合适的东西
相反,如果您接受某种不应为
null
的标识符,并且有人传入了null
,那么愉快地传递NullPointerException
似乎非常合适,而不必包装它。这通常是一个判断调用。您的函数应该公开与其所在层相关的异常。通常这意味着要通过你所呼叫的事物所引发的事件,有时则不然
例如,如果您有一个getAThingy
函数,并且您的应用程序可以进行配置,使所讨论的内容可以来自数据库或文件,那么在数据库情况下,getAThingy
可能不适合引发SqlException
,因为无论是为文件还是数据库配置,调用它的代码都必须处理这个问题。(这将成为一个漏洞百出的抽象。)因此,这将是一个例子,说明您可能应该捕捉并抛出其他更合适的东西
相反,如果您接受某种不应为
null
的标识符,并且有人传入了null
,那么愉快地传递NullPointerException
似乎非常合适,而不必包装它。函数抛出10种不同类型的异常没有什么错,只要每个异常在上下文中都有意义
如果你只是想检测出出什么地方出了问题,但你不需要知道到底是什么,你可以坚持你的方法(即只抛出一个异常)
另一方面,如果需要对不同的问题做出反应,则应保留原始异常
没有“更好”的方法,这取决于上下文和上层需要的信息。您不必担心保持主体或功能原型“干净”,这两种解决方案都是“干净”的。唯一重要的决定因素是对信息的需要。一个函数抛出10种不同类型的异常没有什么错,只要每个异常在上下文中都有意义 如果你只是想检测出出什么地方出了问题,但你不需要知道到底是什么,你可以坚持你的方法(即只抛出一个异常) 另一方面,如果需要对不同的问题做出反应,则应保留原始异常
没有“更好”的方法,这取决于上下文和上层需要的信息。您不必担心保持主体或功能原型“干净”,这两种解决方案都是“干净”的。唯一重要的决策因素是对信息的需要。我听到的关于异常的建议是,尽可能靠近抛出异常的位置处理异常。因此,例如,如果您可以从异常中恢复,请在引发异常的方法中执行恢复,并且根本不执行异常恢复。如果无法从异常恢复,而是代码一层或几层,可以考虑进行。还考虑返回一个简单地指示调用代码需要修复的值。 如果您的异常根本无法从调用层次结构中某个适当位置的代码中恢复,则需要将其转换为用户友好的错误消息,理想情况下是提醒用户如何修复异常并重新运行任务,甚至在发生错误的位置重新启动任务
最后,每当您包装一个异常时,有时您可能希望包装一个异常,将整个异常包装为源,这样您就可以很好地嵌套异常。我听到的关于异常的建议是,处理异常时尽可能靠近抛出异常的位置。因此,例如,如果您可以从异常中恢复,请在引发异常的方法中执行恢复,并且根本不执行异常恢复。如果无法从异常恢复,而是代码一层或几层,可以考虑进行。还考虑返回一个简单地指示调用代码需要修复的值。 如果您的异常根本无法从调用层次结构中某个适当位置的代码中恢复,则需要将其转换为用户友好的错误消息,理想情况下是提醒用户如何修复异常并重新运行任务,甚至在发生错误的位置重新启动任务 最后,每当您包装一个异常时,有时您可能需要
try { /* doing useful work */ }
catch (Whatever t) { throw new MyException(t); }
catch(SomeException ex) {
throw new ClearerException("This is what specifically went wrong", ex);
}