I am trying to understand why using this::someMethod when registering as a listener creates multiple lambda instances each time I register.
For example. The following code is broken and I am trying to understand the rationale for why the java designers implemented it this way.
class A {
private JMenuItem menuItem = new JMenuItem();
public void addListener() {
menuItem.addActionListener(this::clickHandler);
menuItem.removeActionListener(this::clickHandler);
}
private void clickHandler(final ActionEvent e) {
/** do stuff here **/
}
}
If you do the above, the listener is never removed from the JMenuItem. I would have expected that the second lambda would be the same as the first?
Keen to understand why this was done this way.
At runtime, Lambdas are objects, as stated in JLS:
At run time, evaluation of a lambda expression is similar to evaluation of a class instance creation expression, insofar as normal completion produces a reference to an object. Evaluation of a lambda expression is distinct from execution of the lambda body.
Either a new instance of a class (...) is allocated and initialized, or an existing instance of a class (...) is referenced.
So, this explains that:
menuItem.addActionListener(this::clickHandler);
menuItem.removeActionListener(this::clickHandler);
Is similar (but not really the same) to have this:
menuItem.addActionsListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
this.clickHandler(e);
}
});
menuItem.removeActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
this.clickHandler(e);
}
});
This may explain why your code doesn't behave as expected.
Note that the reuse of a lambda as objects depends of JVM implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With