【问题标题】:Java Exception handling within "events"“事件”中的 Java 异常处理
【发布时间】:2009-06-10 14:57:54
【问题描述】:

我想就如何处理“事件”中的异常(按键输入、屏幕更新等)获得第二意见。在这种情况下,我可以控制事件发送者。

所以一个模块被设置为处理一个事件(它实现了一个监听器接口,并针对一个事件发送者进行了注册):

public void DefaultSet ( CardData oldDefault, CardData newDefault )
{
}

事件发送者很简单:

        for ( Enumeration e = listeners.elements(); e.hasMoreElements(); )
        {
            RetrieverListener thisListener = (RetrieverListener) e.nextElement();
            thisListener.DefaultSet( oldDefault, newDefault );
        }

所以如果/当接收器出现问题时:

  • 我是否应该尝试处理那里的异常,并且永远不要向发件人扔回任何东西?有时听众没有正确处理错误的“上下文”,对吗?

  • 是否不赞成将异常抛回事件发送模块,以记录的方式进行处理?例如“抛出 IOException 将导致重置......”。从我读过的 javadocs 来看,这似乎是不标准的。

  • 我是否应该只记录并在出现问题且无能为力时忽略异常?

【问题讨论】:

    标签: java exception events


    【解决方案1】:

    Java 约定是侦听器方法不抛出异常。显然,编程错误可能会使侦听器抛出 RuntimeException,但事件源无法从中恢复,因为它会使程序的对象处于某种未知的、可能不一致的状态。

    因此,由侦听器来捕获已检查的异常并从它们中恢复(例如,回滚事务)或将它们报告给其他对象。我经常使用看起来像这样的 ErrorHandler 接口:

    public interface ErrorHandler {
        public void errorOccurred(String whatIWasTryingToDo, Exception failure);
    }
    

    一个事件监听器告诉它的 ErrorHandler 已经发生的错误。

    public class SomeClass implements SomeKindOfListener 
        private final ErrorHandler errorHandler;
        ... other fields ...
    
        public SomeClass(ErrorHandler errorHandler, ... other parameters ... ) {
            this.errorHandler = errorHandler;
            ...
        }
    
        public void listenerCallback(SomeEvent e) {
            try {
                ... do something that might fail ...
            }
            catch (SomeKindOfException e) {
                errorHandler.errorOccurred("trying to wiggle the widget", e);
            }
        }         
    }
    

    我使用它的实现来初始化事件侦听器,该实现在应用程序中以任何有意义的方式处理故障。例如,它可能会弹出一个对话框、在状态栏中显示一个闪烁的错误图标、记录审核消息或中止进程。

    【讨论】:

    • 有趣的架构和有用的答案,谢谢!我想我的问题是听众并不总是准备好显示东西或提供用户反馈,使用事件确实扭曲了自上而下的堆栈类比,这使得异常如此强大(在堆栈中的适当位置处理异常,可以做某事的地方)。无论如何,我认为听众将不得不以一种或另一种方式处理错误。
    • 您必须设计系统以使侦听器能够处理错误。异常会将堆栈展开回侦听器。侦听器被一些不可能知道如何对异常做出反应的东西调用——例如,在 Swing 事件调度线程或 JMS 提供者的消息传递线程上调用的按钮。您必须在某个位置和时间实例化侦听器,以便为它提供以合理的方式对异常做出反应所需的所有上下文。
    【解决方案2】:

    当您无能为力时,您应该登录并向用户发送消息。如果出现问题可能会损坏数据或在无法恢复时给出错误结果,则应关闭应用程序。

    【讨论】:

      【解决方案3】:

      通常的方法是忽略这个问题。侦听器不应抛出未经检查的异常。

      更好的方法是捕获并记录RuntimeExceptions。这些通常表示编程错误。如果屏幕上的小部件抛出 NPE,那么窗口的其余部分没有理由不完成绘制。然后,用户可以保存他们的数据并重新启动或以其他方式解决该问题。在Errors 的情况下,一般表示情况比较严重,比如OutOfMemeory,抓到只会导致颠簸。没有人愿意这样做。

      【讨论】:

      • "没有理由为什么窗口的其余部分不应该完成绘画" - 当然有;丢失的小部件可能很关键,然后窗口的其余部分可能无用。事实上,它可能毫无用处,似乎在做某事,这比简单的崩溃更糟糕的用户体验。如果程序员没有预料到某个特定的状态,您必须假设该状态刚刚被破坏。
      猜你喜欢
      • 2011-02-01
      • 2011-10-13
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 2016-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多