【问题标题】:Handling exceptions in a Swing UI (low level to high level and exception wrapping)在 Swing UI 中处理异常(从低级到高级和异常包装)
【发布时间】:2011-04-25 20:43:11
【问题描述】:

我希望在 Swing 应用程序中以有意义的方式处理异常。

以下内容位于actionPerformed 方法中。 UiUtils#showError 显示一个带有按钮的 JOptionPane,该按钮显示/隐藏堆栈跟踪。 ApplicationException 是一个自定义类,用于将低级异常转换为用户可以理解的内容。

一个问题是,如果用户没有在此代码之前的JFileChooser 中选择文件,我不确定如何处理向上传播的NullPointerExceptionexportData 方法有目的地检查条目是否为 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 );
    }       
}

【问题讨论】:

    标签: java swing exception-handling


    【解决方案1】:

    要捕获 NullPointerException(或任何 RuntimeException)以及您的 IOException,只需捕获最常见的异常类型:

    try {
       dataService.exportData(list, selectedFile);
    } catch (Exception e) {
       UiUtils.showError(new ApplicationException(e), e );
    } finally {
      ...
    }
    

    您可以通过将原始异常作为“原因”参数添加到构造函数来将原始异常包装到 ApplicationException 中,例如:

    public class ApplicationException extends RuntimeException {
    
       public ApplicationException(Exception cause) {
           super(cause);
       }
    
       ...
    }
    

    那么原始异常将始终可以通过 getCause() 方法获得。

    如果您的程序不是多线程的,我不会担心同时出现异常。

    【讨论】:

      【解决方案2】:

      用户不会理解异常,无论你如何很好地对它们进行涂层或分层;-) 以一种不存在的方式设计每个面向最终用户的应用程序。请记住,例外是针对..好吧..例外状态,仅此而已。

      F.i,空选择是 ui 的一种完全有效的状态,它允许选择某些东西(并作用于选定的项目)。如果作用于空选择作为 NPE 冒泡,则作用逻辑是不正确的 - 它必须处理任何有效状态。应对的一种选择可能是禁用(正如垃圾神已经建议的那样),另一种可能是只要没有选择任何内容就显示警告标签。

      【讨论】:

      • 好点:一些应用程序使用状态栏或工具提示来指导用户禁用控件的原因。
      【解决方案3】:

      作为参考,event dispatch thread 上没有“同时”发生任何事情; EventQueue 强制执行此操作。此外,Swing 会在未捕获的异常上重新启动 EDT,但您可以替换自己的处理程序,如 here 所示。

      附录:@Sasha O 直接解决了这个问题。或者,如果您可以安排从不使用null 文件句柄调用该方法,您可以将assert 作为前提条件。详情请见Programming With Assertions

      这让我想知道在什么情况下应该在方法调用之前或在方法内部检查输入。

      很大程度上取决于设计。不要处理“未选择文件”,而是禁用受影响的控件,直到选择了有效文件。在选择器对话框中按类型、大小或内容过滤文件,而不是处理“没有要导出的数据”。您仍然需要处理 I/O 错误,但这是不可避免的,因为它们在您的程序之外。

      附录:这引发了帮助用户理解为什么禁用控件的问题。一些应用程序使用状态栏来显示此类信息。工具提示可以提供帮助,如 here 所示,即使在禁用的控件上也是如此。

      您应该使用断言来检查公共方法的参数。

      【讨论】:

      • 对旧链接感到抱歉,但那是引入断言的时候。有什么新的建议吗?
      • 关于 EDT 的有趣信息。我已经添加了UncaughtExceptionHandler。断言似乎确实是一个好主意,因为不需要将空参数传递给方法。这让我想知道在什么情况下应该在方法调用之前或在方法内部检查输入。
      • java 断言领域没有任何改变,afaik。当时和现在,检查前提条件正是它们不是的;-)
      • @kleopatra:感谢您对此发表评论。如文章所述,不应使用断言来检查公共方法的参数。目标应该是根本不抛出异常。
      猜你喜欢
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 2012-09-02
      • 2012-11-04
      • 1970-01-01
      • 2013-06-26
      • 2016-06-12
      • 1970-01-01
      相关资源
      最近更新 更多