The following code is taken from Oracle jdk1.8.0_40 AbstractListModel class.
/**
* <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);
}
}
}
My questions are
listeners.length - 2
what about the listeners.length - 1
element? i -= 2
)? A link to the code in openjdk as well.
The listeners
array contains the listeners' Class
objects in the even indices and the listener instances in the odd indices.
Therefore the loop checks the type of each even index in the listeners
array
if (listeners[i] == ListDataListener.class
but fires the event only for odd indices :
((ListDataListener)listeners[i+1]).contentsChanged(e);
listeners.length - 1
is not skipped. Since when i == listeners.length - 2
, i+1 == listeners.length - 1
.
I'm not sure about the reason for the reverse order iteration.
As per the code to add a new listener , shown here:
public void addListDataListener(ListDataListener l) {
listenerList.add(ListDataListener.class, l);
}
the list actually contains pairs of Class
instances and object instances.
With regards to the iteration order, perhaps it's a deliberate approach to notifier newer listeners first?
If you look at EventListenerList: the list is built with two elements, one of them is the listener object, the other the class of the object. That explains the 2-by-2 iteration and the check with the other element towards a class.
I find this code pretty ugly, lots of repetitions of this weird iteration loop. I don't have the answer about this rather strane implementation, but IMO the reasons are probably to keep compatibility with the legacy JAVA -keep the APIs the same, and maybe performances, probably with the introduction of generics in java 1.5.
Wy iterate in reverse order? No idea why it's implemented like that. Maybe an implementation decision or an specification that requires to call latest added listeners first. I tried to find another good reason but I couldn't... Moreover it used to iterate in reverse older since at least 1.6 (I did not check with older versions).
The reason they're iterating in reverse order is so they don't have to evaluate .length
every time. They're doing it as a performance optimization. Here's a related question.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.