JDK中此代码的用途是什么?

Can*_*ell 3 java java-8

以下代码取自Oracle jdk1.8.0_40 AbstractListModel类.

   /**
     * <code>AbstractListModel</code> subclasses must call this method
     * <b>after</b>
     * one or more elements of the list change.  The changed elements
     * are specified by the closed interval index0, index1 -- the endpoints
     * are included.  Note that
     * index0 need not be less than or equal to index1.
     *
     * @param source the <code>ListModel</code> that changed, typically "this"
     * @param index0 one end of the new interval
     * @param index1 the other end of the new interval
     * @see EventListenerList
     * @see DefaultListModel
     */
    protected void fireContentsChanged(Object source, int index0, int index1)
    {
        Object[] listeners = listenerList.getListenerList();
        ListDataEvent e = null;

        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == ListDataListener.class) {
                if (e == null) {
                    e = new ListDataEvent(source, ListDataEvent.CONTENTS_CHANGED, index0, index1);
                }
                ((ListDataListener)listeners[i+1]).contentsChanged(e);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我的问题是

  • 为什么迭代开始在listeners.length - 2怎么样的listeners.length - 1元素?
  • 为什么每个其他元素(i -= 2)触发事件?
  • 为什么迭代的顺序相反?

也是openjdk中代码的链接.

Era*_*ran 6

listeners数组包含Class偶数索引中的侦听器对象和奇数索引中的侦听器实例.

因此,循环检查listeners数组中每个偶数索引的类型

if (listeners[i] == ListDataListener.class
Run Code Online (Sandbox Code Playgroud)

但仅针对奇数指数触发事件:

((ListDataListener)listeners[i+1]).contentsChanged(e);
Run Code Online (Sandbox Code Playgroud)

listeners.length - 1没有被跳过.从什么时候开始i == listeners.length - 2,i+1 == listeners.length - 1.

我不确定逆序迭代的原因.

  • @KDM问题是模型为什么这样做. (3认同)
  • @KDM:这不是解释.毕竟,未指定事件通知的顺序.我的数据模型都使用[Multicaster](http://docs.oracle.com/javase/8/docs/api/java/awt/AWTEventMulticaster.html)模式,该模式根本没有稳定的排序,Swing并不介意.真正的原因似乎是一种深奥的优化,将循环变量与零进行比较被认为比与数组长度的动态值相比更有效. (2认同)