Java 8 has introduced lambda expressions, which is a great thing. But now consider rewriting this code:
class B implements PropertyChangeListener {
void listenToA(A a) {
a.addPropertyChangeListener(this);
}
void propertyChange(PropertyChangeEvent evt) {
switch(evt.getPropertyName()) {
case "Property1":
doSomething();
break;
case "Property2":
doSomethingElse(); case "Property1":
doSomething;
break;
break;
}
void doSomething() { }
void doSomethingElse() { }
}
class A {
final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
}
With lambda expressions and method references, it is no more necessary to have B
implement PropertyChangeListner
as we can write
class B {
void listenToA(A a) {
// using method reference
a.addPropertyChangeListener("Property1", this::doSomething);
// using lambda expression
a.addPropertyChangeListener("Property2", e -> doSomethingElse());
}
void doSomething(PropertyChangeEvent evt) { }
void doSomethingElse() { }
}
class A {
final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcs.addPropertyChangeListener(name, listener);
}
void removePropertyChangeListener(String name, PropertyChangeListener listener) {
pcs.removePropertyChangeListener(name, listener);
}
}
I think the new code is not only shorter but also cleaner and easier to understand. But after reading the answers given here (duplicate of this one, but I think question and answer are more crisp), I can see no way to implement a method called stopListening()
which would remove the listeners again.
I am sure that I am not the first one to stumble on this. So has anyone found a nice solution on how to use method handles as shown in this example and still being able to remove the listeners again later?
UPDATE
That was fast. Building on the answers by Mike Naklis and Hovercraft Full Of Eels, I ended up with this:
class B {
void listenToA(A a) {
a.addPropertyChangeListener("Property1", doSomething);
a.addPropertyChangeListener("Property2", doSomethingElse);
}
final PropertyChangeListener doSomething = evt -> {};
final PropertyChangeListener doSomethingElse = evt -> {};
}
You can declare your listeners as follows:
private final PropertyChangeListener myProperty1Listener = this::doSomething;
private final PropertyChangeListener myProperty2Listener = e -> doSomethingElse());
then, you can add your listeners:
// using method reference
a.addPropertyChangeListener( "Property1", myProperty1Listener );
// using lambda expression
a.addPropertyChangeListener( "Property2", myProperty2Listener );
and you can remove them:
a.removePropertyChangeListener( "Property1", myProperty1Listener );
a.removePropertyChangeListener( "Property2", myProperty2Listener );
You can use lambdas and still use variables. For example, if you had:
class B {
private PropertyChangeListener listener1 = this::doSomething;
private PropertyChangeListener listener2 = e -> doSomethingElse();
void listenToA(A a) {
// using method reference
a.addPropertyChangeListener("Property1", listener1);
// using lambda expression
a.addPropertyChangeListener("Property2", listener2);
}
Then it would be easy to remove listener1 or listener2 when and where needed.
Also there are other ways, since the PropertyChangeSupport object has a getPropertyChangeListeners()
that would allow removal of all listeners in a for loop if need be.
class A {
final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcs.addPropertyChangeListener(name, listener);
}
void removePropertyChangeListener(String name, PropertyChangeListener listener) {
pcs.removePropertyChangeListener(name, listener);
}
public void removeAllListeners() {
for (PropertyChangeListener l : pcs.getPropertyChangeListeners()) {
pcs.removePropertyChangeListener(l);
}
}
}
来源:https://stackoverflow.com/questions/42146360/how-do-i-remove-lambda-expressions-method-handles-that-are-used-as-listeners