
476
|
Chapter 12, Miscellany
#94 Fire Events and Stay Bug Free
HACK
The obvious question here is: why didn’t D get called? Well, think about it:
you iterate over the listeners by index, from 0 to 4. On index 2, the code
calls
C
’s
handleEvent( )
, which removes itself from the
ArrayList
. As a result,
D
, which was at index 3, is now at index 2. But having serviced index 2
(which was
C
), the
for
loop moves on to index 3, which is now listener
E
.
Thus,
D
never gets called.
That was a lot of fun the first time I got to debug it.
Hacking a Solution
Consider an alternative approach. Counting up gets you in trouble because a
listener that removes itself shifts the indices of all subsequent listeners. But if
you counted down—from the last listener to the first—then a listener could
remove itself safely.
In these examples, this would mean counting from index 4 down to 0. On
index 2, listener
C removes itself, but that doesn’t change the indices of the
listeners that haven’t been called yet, which are at indices 0 and 1.
All you have to do is change the
fireEvent( ) method in the
BackwardsForLoopEventSource class:
public void fireEvent (EventObject o) {
for (int i=listeners.size( )-1; i>=0; i--) {
TestEventListener l = (TestEventListener) listeners.get(i);
l.handleEvent (o);
}
}
Run this modified code and you get the output shown here:
[tonberry] cadamson% java BackwardsForLoopEventSource
E called
D called
C called
B called