To illustrate the concept with a quick (crude) example, consider the following:
public interface ChangeHandler {
public void handleChange();
}
public class FileMonitor {
private File file;
private Set<ChangeHandler> handlers = new HashSet<ChangeHandler>();
public FileMonitor(File file) {
this.file = file;
}
public void registerChangeHandler(ChangeHandler handler) {
this.handlers.add(handler);
}
public void unregisterChangeHandler(ChangeHandler handler) {
this.handlers.remove(handler);
}
...
}
If a client class then uses this FileMonitor
API, they might do this:
public class MyClass {
File myFile = new File(...);
FileMonitor monitor = new FileMonitor(myFile);
public void something() {
...
ChangeHandler myHandler = getChangeHandler();
monitor.registerChangeHandler(myHandler);
...
}
}
If the author of the MyClass
then forgets to call unregisterChangeHandler()
when it's done with the handler, the FileMonitor
's HashSet
will forever reference the instance that was registered, causing it to remain in memory until the FileMonitor
is destroyed or the application quits.
To prevent this, Bloch is suggesting using a weak-referencing collection instead of the HashSet
, so that if your instance of MyClass
is destroyed, the reference will be removed from the monitor's collection.
You might replace the HashSet
in FileMonitor
with a WeakHashMap
and use the handlers as the keys, since the latter will automatically remove the handler from the collection when all other references to the object are gone.