如何删除用作侦听器的 lambda expressions/method 句柄?
How do I remove lambda expressions/method handles that are used as listeners?
Java 8推出了lambda expressions,这是一件了不起的事情。但现在考虑重写这段代码:
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);
}
}
使用 lambda 表达式和方法引用,不再需要 B
实现 PropertyChangeListner
,因为我们可以编写
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);
}
}
我认为新代码不仅更短,而且更清晰、更容易理解。但是在阅读了 (duplicate of this 给出的答案后,但我认为问题和答案更清晰),我看不出有什么办法可以实现一个名为 stopListening()
的方法,它会再次删除监听器。
我相信我不是第一个偶然发现这个问题的人。那么有没有人找到一个很好的解决方案,说明如何使用方法句柄,如本例所示,并且仍然能够在以后再次删除侦听器?
更新
真快。基于 Mike Naklis 和 Hovercraft Full Of Eels 的回答,我得到了这个:
class B {
void listenToA(A a) {
a.addPropertyChangeListener("Property1", doSomething);
a.addPropertyChangeListener("Property2", doSomethingElse);
}
final PropertyChangeListener doSomething = evt -> {};
final PropertyChangeListener doSomethingElse = evt -> {};
}
您可以按如下方式声明您的监听器:
private final PropertyChangeListener myProperty1Listener = this::doSomething;
private final PropertyChangeListener myProperty2Listener = e -> doSomethingElse());
然后,您可以添加您的听众:
// using method reference
a.addPropertyChangeListener( "Property1", myProperty1Listener );
// using lambda expression
a.addPropertyChangeListener( "Property2", myProperty2Listener );
您可以删除它们:
a.removePropertyChangeListener( "Property1", myProperty1Listener );
a.removePropertyChangeListener( "Property2", myProperty2Listener );
您可以使用 lambda 并仍然使用变量。例如,如果您有:
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);
}
然后在需要的时间和地点移除 listener1 或 listener2 就很容易了。
还有其他方法,因为 PropertyChangeSupport 对象有一个 getPropertyChangeListeners()
允许在需要时删除 for 循环中的所有侦听器。
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);
}
}
}
Java 8推出了lambda expressions,这是一件了不起的事情。但现在考虑重写这段代码:
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);
}
}
使用 lambda 表达式和方法引用,不再需要 B
实现 PropertyChangeListner
,因为我们可以编写
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);
}
}
我认为新代码不仅更短,而且更清晰、更容易理解。但是在阅读了 stopListening()
的方法,它会再次删除监听器。
我相信我不是第一个偶然发现这个问题的人。那么有没有人找到一个很好的解决方案,说明如何使用方法句柄,如本例所示,并且仍然能够在以后再次删除侦听器?
更新
真快。基于 Mike Naklis 和 Hovercraft Full Of Eels 的回答,我得到了这个:
class B {
void listenToA(A a) {
a.addPropertyChangeListener("Property1", doSomething);
a.addPropertyChangeListener("Property2", doSomethingElse);
}
final PropertyChangeListener doSomething = evt -> {};
final PropertyChangeListener doSomethingElse = evt -> {};
}
您可以按如下方式声明您的监听器:
private final PropertyChangeListener myProperty1Listener = this::doSomething;
private final PropertyChangeListener myProperty2Listener = e -> doSomethingElse());
然后,您可以添加您的听众:
// using method reference
a.addPropertyChangeListener( "Property1", myProperty1Listener );
// using lambda expression
a.addPropertyChangeListener( "Property2", myProperty2Listener );
您可以删除它们:
a.removePropertyChangeListener( "Property1", myProperty1Listener );
a.removePropertyChangeListener( "Property2", myProperty2Listener );
您可以使用 lambda 并仍然使用变量。例如,如果您有:
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);
}
然后在需要的时间和地点移除 listener1 或 listener2 就很容易了。
还有其他方法,因为 PropertyChangeSupport 对象有一个 getPropertyChangeListeners()
允许在需要时删除 for 循环中的所有侦听器。
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);
}
}
}