I want to register a JavaFX ListChangeListener
to an ObservableList
. However I noticed, that under certain circumstances the Listener is not getting called.
(1) If the Listener is a method reference, everything works:
// using a direct method reference:
private final ListChangeListener<String> listener = this::listDidChange;
/* ... */
public void init() {
list.addListener(listener);
}
(2) If however the Listener is a weak ref to the same method, the listener is NOT invoked:
// using a weak method reference:
private final ListChangeListener<String> listener = new WeakListChangeListener<String>(this::listDidChange);
/* ... */
public void init() {
list.addListener(listener);
}
(3) Now the really funny part is, that this is working again, even though it should be the same as the previous example:
// direct method reference wrapped into a weak ref later:
private final ListChangeListener<String> listener = this::listDidChange;
/* ... */
public void init() {
list.addListener(new WeakListChangeListener<String>(listener));
}
Two questions:
- What exactly happens, when a weak ref to a method ref is created?
- What is the difference between (2) and (3)?
Creating a method reference (in this case) is just like creating any other object. So if we replace it with a
new
expression, example 2 becomes like:Whereas example 3 would be:
Now the difference becomes fairly obvious:
Foo
is instantly eligible for garbage collection, as nothing holds a strong reference to it.Foo
object in yourlistener
field, so it will only be collected when the object with thelistener
field is collected.P.s.: If method references in Java really were references to methods, meaning that methods were first-class objects in their own right (like in Javascript), example 2 would work too as every object would implicitly hold a reference to all their methods.