我正在考虑一个设计,在Swing应用程序中使用自定义UncaughtExceptionHandler处理所有致命异常。这将包括意外的RuntimeExceptions,但也包括在关键资源不可用或以其他方式失败时引发的自定义异常(例如,找不到设置文件或服务器通信错误)。 UncaughtExceptionHandler将根据特定的自定义异常(以及所有未预料到的异常)执行不同的操作,但在所有情况下,应用程序都会向用户显示错误消息并退出。另一种方法是为所有未预料到的异常保留UncaughtExceptionHandler,但处理接近其原点的所有其他致命场景。
我考虑的设计是否合理,或者我应该使用替代品吗?用于处理致命异常的典型方法是什么?
答案 0 :(得分:2)
通常,很难找到一个好的异常处理策略。每种方法都有其缺点。特别是,你的在某种意义上是好的(处理失败的集中位置)但是有这个缺陷:
您正在描述的异常处理程序将对每个可能的异常进行特殊处理。随着时间的推移,它将成为您的应用程序的焦点:每次添加新功能时,您还需要向处理程序添加异常处理逻辑。这意味着:
另一个问题是错误恢复。抛出异常(并向用户显示一些通知)后,用户希望继续使用该应用程序。这意味着如果您的代码开始修改内部数据结构然后因异常而停止,则在允许用户进行其他交互之前,您需要撤消这些修改(或者至少使数据结构恢复到可行状态)。要实现这一目标,需要重新思考数据的组织方式。一种可能的解决方案是DB事务。另一方面,这种表示比普通的数据结构更复杂,因此您需要根据应用程序的需求进行权衡(它是玩具/原型吗?)
答案 1 :(得分:1)
我在大型Swing应用程序中成功使用了本地处理和集中处理的混合。集中处理程序只处理我认为两个或三个特定类型,以及所有未捕获的异常。已经有一段时间了,所以我不记得所有细节,但我们最终得到了一个集中处理程序,它处理了两到三种特定类型的异常和所有未捕获的异常。
我们尽可能使用本地处理,但也定义了类似于ErrorMessageException的东西,它也可以从不与UI交互的后台线程抛出。此异常在中央处理程序中具有特定处理。我们认为这不是最漂亮的解决方案,但它简单易行且运行良好。
任何未捕获的异常都被视为“一般错误”或类似的东西。工作得很好,当然我们试图发布不会导致任何未处理的异常的代码。但是,这在测试中非常有用。
通过这种方法,集中处理程序易于维护,并且没有意外增长。我们也没有看到紧耦合的任何症状,实际上恰恰相反。
答案 2 :(得分:0)
将main
方法的逻辑包装在try
catch
块中会更直截了当; e.g。
public static void main(String[] args) {
try {
// everything happens here
System.exit(0);
} catch (SpecificException ex) {
...
} catch (AnotherException ex) {
...
} catch (Throwable ex) {
// deal with anything else.
...
}
System.exit(1); // tell the world that we failed.
}
答案 3 :(得分:0)
如果您有多线程应用程序(如大多数Swing应用程序),您可能需要考虑通过某个异步队列将异常发送到中央异常处理线程。