This Java tip shows you how to use reference objects, introduced in JDK 1.2, to solve this problem. By interacting with the garbage collector, you can eliminate loiterers and lapsed listeners, terms suggested by Ed Lycklama (see the Resources section below for more details). Lycklama generally defines a loiterer as an object that persists past its usefulness. The loiterer category is further broken down into four patterns; most common is the lapsed listener, an object added to, but never removed from, a collection of listeners.
In this article, I'll examine a simple Swing MVC application to illustrate how an application using the MVC pattern creates lapsed listeners and memory leaks. Then, I'll show you how to modify the application in order to remove the memory leaks. The example application has a simple data model that contains some strings. The application's main window, shown in Figure 1, lets the user add new strings to, and create new views of, the data model. Both processes are illustrated in the figure below. The application's main window also shows the number of views that are alive, meaning that they are created, but not yet finalized. Each view is a separate frame containing a Jlist, which displays the strings from the data model (not shown here). A view listens to changes in the data model and updates itself accordingly. You will find the full source for this example in Resources.

Figure 1. The application's main window
First, I am going to define the example data model, but not implement it. Then, I'll implement that model's view. Finally, I'll actually implement the data model in four different ways, showing different implementation trade-offs.
The interface VectorModel defines the data model of the example application:
VectorModel.java
package mldemo; import java.util.*; /** * Define a simple "application" data model. You can add, remove, and * access objects. When you add or remove an object, all * registeredVectorModel.Listeners * will be notified with aVectorModel.Event. * * @author Raimond Reichert */ public interface VectorModel { public static class Event extends EventObject { private Object element; public Event (VectorModel model, Object element) { super (model); this.element = element; } public Object getElement() { return element; } } public interface Listener extends EventListener { public void elementAdded (VectorModel.Event e); public void elementRemoved (VectorModel.Event e); } public void addElement (Object object); public void removeElement (Object object); public Object elementAt (int index); public int size(); public void addListener (VectorModel.Listener l); public void removeListener (VectorModel.Listener l); }
Whenever an element is added to or removed from the vector, the VectorModel's implementations must notify their listeners.
java.lang.refjava.lang.ref packageListener interface, and to implement the Event class, within VectorModel. I think this is a very appropriate use of top-level, nested classes