How do I remove lambda expressions/method handles that are used as listeners?

拥有回忆 提交于 2019-11-28 08:01:26

问题


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 -> {};
}

回答1:


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 );



回答2:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!