如何创建新对象并保留侦听器与同类型的旧对象

时间:2015-04-25 18:08:36

标签: java

我使用实现的PropertyChangeSupport类Flight,如下所示:

protected List changeListeners;

public void addPropertyChangeListener(PropertyChangeListener listenerToAdd){...}

public void removePropertyChangeListener(PropertyChangeListener listenerToRemove){...}

private void notifyChangeListeners(String message){...}

......经典的观察者模式。我想要完成的是创建新的Flight对象,但保留现有的PropertyChangeListeners。看起来简单的任务让我深入研究了多线程和并发问题,发现了“失效的倾听者问题”。

这是我的第一个“简单解决方案”,它不起作用:

public Flight newFlightWithOldListeners(List<Scans> scansList){
    Flight newFlight=new FlightImpl();
    newFlight.setScansList(scansList);
    newFlight.setExplorerManager(this.getExplorerManager());
    for (Iterator<PropertyChangeListener> iterator = this.getChangeListeners().iterator(); iterator.hasNext();) {
        PropertyChangeListener listener=iterator.next();
        newFlight.addPropertyChangeListener(listener);
        iterator.remove();
    }
    return newFlight;
}

我没有收到任何错误,但这并不是应该的。所有PropertyChangeListeneres都保持链接到旧的Flight对象,并且在触发PropertyChangeEvents之前会触发它。

我完全错过逻辑吗?这看起来应该是微不足道的?

问题是关于设计。这是使用旧PropertyChangeListeners创建新对象的好设计吗?

2 个答案:

答案 0 :(得分:6)

您在迭代时不能直接更改基础集合,否则您将获得ConcurrentModificationException。您应该使用迭代器的remove()方法。

而不是

this.changeListeners.remove(iterator.next());

只是做

iterator.remove()

至于你应该做的逻辑

for (Iterator<PropertyChangeListener> iterator = this.getChangeListeners().iterator(); iterator.hasNext();) {
    PropertyChangeListener propertyChangeListener   = (PropertyChangeListener )iterator.next();
    newFlight.addPropertyChangeListener(propertyChangeListener);
    iterator.remove();
}

答案 1 :(得分:0)

我怀疑您因iterator而遇到问题,因为您在创建changeListers后修改(删除元素)iterator。在大多数情况下,iterator不允许我们从外部更改list。使用iterator.remove()这将解决。