关于Java的事件监听机制,我们首先需了解三个概念:


1.事件源(Event Source):即触发事件的对象,比如:Button对象可以修改按钮的状态,也就是说Button对象可以出发按钮按下这个事件。


2.事件状态对象(Event Object):描述事件的对象,对于一类特定的事件,我们需要记录事件发生时的一些状态,比如说事件触发的时间、按钮按下的次数(单击还是双击)、触发事件的对象(即事件源)、对事件的描述等等。我们需要一个专门描述这些状态的事件对象EventObject。


3.事件监听器(Event Listener):当我们打开QQ时,点击登陆按钮,立即显示出了好友列表的界面。即当登陆这个按钮被点击后(即点击事件被触发),程序执行了密码验证登陆QQ拉取好友列表等操作。那么,是哪些对象执行了这些操作呢?这些对象又是如何知道何时执行这些操作的呢?这便提出了事件监听的概念,对于在按钮点击后需要进行操作的那些对象,注册事件监听器(即实现ActionListener接口),并且实现actionPerformed(ActionEvent)方法,在这个方法中是对象在事件触发后具体的操作。JDK中的源码如下:

public interface ActionListener extends EventListener {
     /**
      * Invoked when an action occurs.
      */
     public void actionPerformed(ActionEvent e);
 }



那么以上的三种对象是如何关联起来的呢?下面我们以Java的JButton类的实现描述一下三者的关系

在JDK源码中,我们可以发现,JButton继承AbstractButton类:

public class JButton extends AbstractButton implements Accessible
JButton类和AbstractButton类即我们上面提到的事件源
在AbstractButton类中,有一个方法addActionListener(ActionListener) 
public void addActionListener(ActionListener l) {
        listenerList.add(ActionListener.class, l);
     }listenerList是AbstractButton类的一个成员变量
 protected EventListenerList listenerList = new EventListenerList();
EventListenerList是一个比较简单的类,我们贴出这个类的源码如下:
public class EventListenerList implements Serializable {
     /* A null array to be shared by all empty listener lists*/
     private final static Object[] NULL_ARRAY = new Object[0];   /* The list of ListenerType - Listener pairs */
     protected transient Object[] listenerList = NULL_ARRAY;

     public Object[] getListenerList() {
         return listenerList;
     }


     /**
      * Return an array of all the listeners of the given type.
      * @return all of the listeners of the specified type.
      * @exception  ClassCastException if the supplied class
      *          is not assignable to EventListener
      *
      * @since 1.3
      */
     public <T extends EventListener> T[] getListeners(Class<T> t) {
         Object[] lList = listenerList;
         int n = getListenerCount(lList, t);
         T[] result = (T[])Array.newInstance(t, n);
         int j = 0;
         for (int i = lList.length-2; i>=0; i-=2) {
             if (lList[i] == t) {
                 result[j++] = (T)lList[i+1];
             }
         }
         return result;
     }
     /**
      * Returns the total number of listeners for this listener list.
      */
     public int getListenerCount() {
         return listenerList.length/2;
     }
     /**
      * Returns the total number of listeners of the supplied type
      * for this listener list.
      */
     public int getListenerCount(Class<?> t) {
         Object[] lList = listenerList;
         return getListenerCount(lList, t);
     }

     private int getListenerCount(Object[] list, Class t) {
         int count = 0;
         for (int i = 0; i < list.length; i+=2) {
             if (t == (Class)list[i])
                 count++;
         }
         return count;
     }
     /**
      * Adds the listener as a listener of the specified type.
      * @param t the type of the listener to be added
      * @param l the listener to be added
      */
     public synchronized <T extends EventListener> void add(Class<T> t, T l) {
         if (l==null) {
             // In an ideal world, we would do an assertion here
             // to help developers know they are probably doing
             // something wrong
             return;
         }
         if (!t.isInstance(l)) {
             throw new IllegalArgumentException("Listener " + l +
                                          " is not of type " + t);
         }
         if (listenerList == NULL_ARRAY) {
             // if this is the first listener added,
             // initialize the lists
             listenerList = new Object[] { t, l };
         } else {
             // Otherwise copy the array and add the new listener
             int i = listenerList.length;
             Object[] tmp = new Object[i+2];
             System.arraycopy(listenerList, 0, tmp, 0, i);


             tmp[i] = t;
             tmp[i+1] = l;


             listenerList = tmp;
         }
     }
     /**
      * Removes the listener as a listener of the specified type.
      * @param t the type of the listener to be removed
      * @param l the listener to be removed
      */
     public synchronized <T extends EventListener> void remove(Class<T> t, T l) {
         if (l ==null) {
             // In an ideal world, we would do an assertion here
             // to help developers know they are probably doing
             // something wrong
             return;
         }
         if (!t.isInstance(l)) {
             throw new IllegalArgumentException("Listener " + l +
                                          " is not of type " + t);
         }
         // Is l on the list?
         int index = -1;
         for (int i = listenerList.length-2; i>=0; i-=2) {
             if ((listenerList[i]==t) && (listenerList[i+1].equals(l) == true)) {
                 index = i;
                 break;
             }
         }
         // If so,  remove it
         if (index != -1) {
             Object[] tmp = new Object[listenerList.length-2];
             // Copy the list up to index
             System.arraycopy(listenerList, 0, tmp, 0, index);
             // Copy from two past the index, up to
             // the end of tmp (which is two elements
             // shorter than the old list)
             if (index < tmp.length)
                 System.arraycopy(listenerList, index+2, tmp, index,
                                  tmp.length - index);
             // set the listener array to the new array or null
             listenerList = (tmp.length == 0) ? NULL_ARRAY : tmp;
             }
     }


     // Serialization support.
     private void writeObject(ObjectOutputStream s) throws IOException {
         Object[] lList = listenerList;
         s.defaultWriteObject();


         // Save the non-null event listeners:
         for (int i = 0; i < lList.length; i+=2) {
             Class<?> t = (Class)lList[i];
             EventListener l = (EventListener)lList[i+1];
             if ((l!=null) && (l instanceof Serializable)) {
                 s.writeObject(t.getName());
                 s.writeObject(l);
             }
         }


         s.writeObject(null);
     }


     private void readObject(ObjectInputStream s)
         throws IOException, ClassNotFoundException {
         listenerList = NULL_ARRAY;
         s.defaultReadObject();
         Object listenerTypeOrNull;


         while (null != (listenerTypeOrNull = s.readObject())) {
             ClassLoader cl = Thread.currentThread().getContextClassLoader();
             EventListener l = (EventListener)s.readObject();
             String name = (String) listenerTypeOrNull;
             ReflectUtil.checkPackageAccess(name);
             add((Class<EventListener>)Class.forName(name, true, cl), l);
         }
     }


     /**
      * Returns a string representation of the EventListenerList.
      */
     public String toString() {
         Object[] lList = listenerList;
         String s = "EventListenerList: ";
         s += lList.length/2 + " listeners: ";
         for (int i = 0 ; i <= lList.length-2 ; i+=2) {
             s += " type " + ((Class)lList[i]).getName();
             s += " listener " + lList[i+1];
         }
         return s;
     }
 }


分析上面的源码我们可以发现,EventListenerList是一个存储Object对象的类,它的成员变量listenerList 就是一个Object对象数组,这个类主要用于操作这个对象数组,在AbstractButton类的addActionListener方法中,listenerList调用了add方法添加事件监听器。

由上面的分析可以看出,在事件源中添加事件监听器,每个等待事件触发需要进行操作的对象都实现了事件监听器接口,然后事件源对象调用addActionListener方法添加等待操作的事件触发器,一个事件源可以添加多个事件监听器。

当事件触发时,事件源对象会调用存在该对象中的listenerList中的每个监听器的actionPerformed的方法实现监听对象的操作。这便是Java的事件监听机制的部分原理。虽然源码读起来有些难度,但大家在读源码的时候关键是理解其中体现出的设计思想,一定不要仅仅拘泥于代码层面


有些内容限于本人技术水平有限,可能讲的比较啰嗦,如有不足读者可以提出,大家一起讨论。