何时使用EventListenerList而不是一般的侦听器集合

当我学习如何在Java中激活事件时,我熟悉了EventListenerList。 当我创建自己的侦听器时,我编写了侦听器,因此它扩展了EventListener,我将它们存储在EventListenerList中,我的fire方法将遍历事件侦听器,如下所示:

protected void fireChangeOccurred(Change change) { Object[] listeners = listenerList.getListenerList(); for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==ChangeListener.class) { ((ChangeListener)listeners[i+1]).changeOccurred(change); } } } 

现在我正在查看简单地将侦听器放入HashMap的代码(可以是任何集合),侦听器接口不会扩展EventListener,而fire方法如下所示:

 protected void fireChangeOccurred(Change change) { for (ChangeListener listener : listeners) { listener.changeOccurred(change); } } 

使用EventListenerList而不仅仅是维护我自己的监听器列表有什么好处? 只有侦听器在Swing组件中才真正有用 – 对于事件调度线程是否重要?

对我来说, EventListenerList的主要优点是,如果包含的类具有(或可能具有)多种类型的侦听器。 许多Swing组件都可以; 你正在审查的那个可能没有。 第二个例子较短,但它具有隐含的设计限制。

EventListenerList有一个方法 getListeners(Class t) ,特别适用于您只对一种事件类型感兴趣的情况。

以下是如何使用它的示例:

 protected void fireChangeOccurred(Change change) { for (ChangeListener listener: listenerList.getListeners(ChangeListener.class)) { listener.stateChanged(new ChangeEvent(this)); } } 

如果您选择维护自己的侦听器集合,我建议使用CopyOnWriteArrayList

这几天没有巨大的优势。 只是小优化。 这是JavaDocs所说的:

这个类提供的主要好处是,在没有监听器的情况下它相对便宜,并且它在一个地方提供事件监听器列表的序列化,以及一定程度的MT安全性(正确使用时)

使用现代JVM和集合,这无关紧要。 但是你可以用你自己的实现做的是提供在EDT上触发更改的方法,如果你使用Swing – 这将是有益的。