我分析了我正在使用Java源代码分析器的代码。其中一个警告是“始终将用户定义的异常声明为最终”。还有许多其他警告没有多大意义,但这个让我有点困惑。
我正在研究一个框架,我有一个根通用异常(比如FrameworkGenericException),对于其他异常,我只是从根异常中导出它们。所以我有一个框架的例外层次结构。我可能会扩展层次结构,但我认为这个警告告诉我不要有这样的层次结构,而是单独定义它们。那么我应该采用哪种方式,你的意见是什么?
答案 0 :(得分:4)
这可能是他们的标准做法:如果不应该继承类,则将类声明为final,并且他们可能认为所有异常都不会从中扩展。
但是,在您的情况下,我认为制作一个通用异常并从中扩展所有其他异常是一件好事。说,你有:
public void frameworkMethod() throws IllegalDataException, InvalidCommandException;
这些例外是FrameworkException
的子类。然后你可以更轻松地处理异常。
try {
frameworkMethod();
} catch (FrameworkException ex) {
logger.log(Level.SEVERE, "An exception occured!", ex);
if (ex instanceof IllegalDataException) {
// Do something to recover
} else if (ex instanceof InvalidCommandException) {
//Inform the user
} //And so on...
}
所以我会说,你做的是正确的,你的程序架构将更容易使用。
答案 1 :(得分:2)
我从来没有听说过这个建议,对我来说也没有任何意义。
您使用的是哪种工具?我尝试使用谷歌搜索该消息并从你的SO问题中获得零点击。尝试其他搜索试图“利用网络的智慧”也没有给我任何明显的相关性。
也许你应该让代码分析工具的作者解释这种风格规则的基本原理......
答案 2 :(得分:2)
奇怪。 Google只会显示一个包含此类文字的文档 - 您的问题:)
在我的项目中,为所有异常设置用户定义的祖先是很正常的。这种风格很少有几年的发展,到目前为止没有什么特别的。
答案 3 :(得分:2)
问题是,静态分析工具基本上会扫描您的代码是否违反(该工具的作者认为是“最佳实践”)。在这种情况下,通常认为具有非常浅的异常层次结构的“最佳实践”。
原因是当你遇到异常时基本上有两次。第一个是,你想要捕获异常,因为你知道如何处理它。例如:
try
{
return fetchDataFromFile();
}
catch(FileNotFoundException)
{
return defaultData;
}
在这种情况下,您捕获了FileNotFoundException
,因为您希望在找不到文件时返回“默认数据”。在这种情况下,您通常会捕获特定的异常类 - 因为这是您知道如何处理的唯一异常类型(例如,如果fetchDataFromFile
抛出其他异常,则不会希望它返回默认数据。
另一次你将捕获异常是你线程的根本,
try
{
doStuff();
catch(Exception e)
{
logException(e);
notifyUser(e);
}
在这种情况下,您将捕获根异常类,因为您特别希望所有异常,以便您可以记录它们,或通知用户。
在极少数情况下您需要做其他事情。
现在,请记住这是一个静态分析工具。它的工作就是向您发出“潜在”问题。如果您认为您的情况有所不同,那么您的想法就是记录为什么您认为它不同并且特别禁用该部分代码(或该类或其他)的警告。
答案 4 :(得分:2)
如果你把你的通用异常抽象化,我敢打赌这条消息会消失。你将关注另一位受人尊敬的面向对象的大师Scott Meyer:
使非叶类抽象化。
就个人而言,我不同意整个框架的根异常。你在其中嵌入了什么非凡的行为,所有的孩子都将继承java.lang.Throwable
以外的所有行为?
我认为让SpecialBusinessException
覆盖java.lang.RuntimeException
中的四个构造函数是充足的。层次结构有什么意义?我敢打赌它是扁平的,有一个根类。为什么要这么麻烦?