Doesn't JavaFX (or Java) need additional support for Java 8 Lambdas?

Viewed 133

When using a lambda expression to add a listener to some JavaFX property, we might fall into a classic trap where we will be facing memory leaks or where the listener we set won't be invoked:

void init() {
    someProperty.addListener(this::onChanged); // might create a memory leak
    someProperty.addListener(new WeakChangeListener<String>(this::onChanged)); // no memory leak, but the listener won't be called
}

The following solution works:

private final ChangeListener<String> changeListener = this::onChanged;

void init() {
    someProperty.addListener(new WeakChangeListener<>(changeListener)); // OK, but requires an extra field + WeakChangeListener
}

Is there any other solution to set a listener with a lambda without much boilerplate code?

Edit: An other confusing situation exists, while not related to Lambda expressions but still related to the usage of weak references with JavaFX, where the following code won't work:

private final ObservableList<Person> persons = FXCollections.observableArrayList();

public ObservableList<Person> getPersons() {
    return FXCollections.unmodifiableObservableList(persons); // a client invoking getPersons().addListener(someListener) won't be notified
}

But this code will work (with some additional boilerplate code though):

private final ObservableList<Person> persons = FXCollections.observableArrayList();
private final ObservableList<Person> immutableList = FXCollections.unmodifiableObservableList(persons); // needed for our clients to be notified

@SuppressWarnings("ReturnOfCollectionOrArrayField") // needed to avoid a warning
public ObservableList<Person> getPersons() {
    return this.immutableList;
}

I'm using the word "confusing" here because:

  • The working solution is not the one we come first; it's not "natural".
  • When we face the problem for the very first time, it takes hours before we understand where the problem comes from.
0 Answers
Related