10

Java 8 引入了lambda 表达式,这是一件很棒的事情。但现在考虑重写这段代码:

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

2 回答 2

11

您可以按如下方式声明您的侦听器:

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 );
于 2017-02-09T20:42:19.177 回答
1

您可以使用 lambdas 并仍然使用变量。例如,如果您有:

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);
        }
    }
}
于 2017-02-09T20:43:01.597 回答