我希望在Swing应用程序中以有意义的方式处理异常。
以下是actionPerformed
方法。 UiUtils#showError
显示一个JOptionPane,其中包含一个显示/隐藏堆栈跟踪的按钮。 ApplicationException是一个自定义类,用于将低级异常转换为用户可以理解的内容。
一个问题是,如果用户在此代码之前未在NullPointerException
中选择文件,我不确定如何处理传播的JFileChooser
。 exportData
方法有目的地在条目上检查null,因此不进行文件处理。
此外,似乎这是一个很好的方法来包装低级Exception
(例如来自数据层)。我想修改ApplicationException
以保留实例,而不是在showError
方法中执行此操作。
最后,有一件事困扰着我,这可能是一些例外同时发生的可能性。我不知道如何处理这个,所以我愿意接受任何建议。
try {
dataService.exportData(list, selectedFile);
} catch (IOException e) {
UiUtils.showError(new ApplicationException("Input/Ouput error"), e );
} finally {
if( list == null){
UiUtils.showError(new ApplicationException("No data to export"), null );
}
if( selectedFile == null ){
UiUtils.showError(new ApplicationException("No file selected"), null );
}
}
答案 0 :(得分:2)
要捕获NullPointerException(或任何RuntimeException)以及IOException,请捕获最常见的异常类型:
try {
dataService.exportData(list, selectedFile);
} catch (Exception e) {
UiUtils.showError(new ApplicationException(e), e );
} finally {
...
}
通过将原始异常作为“cause”参数添加到构造函数中,可以将原始异常包装到ApplicationException中,例如:
public class ApplicationException extends RuntimeException {
public ApplicationException(Exception cause) {
super(cause);
}
...
}
然后,原始异常将始终通过getCause()方法提供。
如果您的程序不是多线程的,我不会担心同时发生异常。
答案 1 :(得分:1)
作为参考,event dispatch thread上没有“同时”发生任何事情; EventQueue
强制执行此操作。此外,Swing会在未捕获的异常上重新启动EDT,但您可以替换自己的处理程序,如here所示。
附录:@Sasha O直接帮助解决了这个问题。或者,如果您可以安排永远不会使用null
文件句柄调用该方法,则可以assert
将该事实作为前提条件。有关详细信息,请参阅Programming With Assertions。
这让我想知道在什么情况下应该在方法调用之前或在方法内部检查输入。
很大程度上取决于设计。而不是处理“未选择文件”,禁用受影响的控件,直到选择了有效文件。而不是处理“无数据导出”,而是按选择器对话框中的类型,大小或内容过滤文件。您仍然需要处理I / O故障,但这是不可避免的,因为它们是您的程序的外部。
附录:这引发了帮助用户理解禁用控件的原因的问题。某些应用程序使用状态栏来显示此类信息。即使在禁用的控件上,工具提示也可以提供帮助,如here所示。
你应该不使用断言来检查公共方法的参数。
答案 2 :(得分:1)
用户不会理解异常,但是很好地将它们涂层或分层;-)以没有任何方式设计每个最终用户目标应用程序。并且请记住,例外情况是......好的......特殊状态,没有别的。
F.i,空选择是一个完全有效的ui状态,它允许选择某些东西(并对所选项目采取行动)。如果作为NPE在空选择中起作用,则表示逻辑不正确 - 它必须处理任何有效状态。应对的一个选择可能是禁用(已经建议使用trashgod),另一个可能是显示警告标签,只要没有选择。