【问题标题】:How to make new object and preserve Listeners from old object of the same type如何从相同类型的旧对象中创建新对象并保留侦听器
【发布时间】:2015-07-04 07:37:46
【问题描述】:

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

受保护的列表 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 创建新对象的好设计吗?

【问题讨论】:

  • 确切的例外是什么?哪一行代码抛出了这个异常?答案可能很明显,但可以肯定的是,我们需要更多细节。

标签: java


【解决方案1】:

您不能在迭代时直接更改基础集合,否则您将得到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();
}

【讨论】:

  • 感谢 iterator.remove(),这删除了 ​​ConcurrentModificationException,但我缺少的与逻辑有关。代码没有按应有的方式行事。我从旧的 FlightImpl 对象获取 propertyChangeEvents,而新对象 (newFlight) 没有注册 PropertyChangeListeners。也许我应该从旧对象或类似的东西中克隆 PropertyChangeListener?必须有一些更简单的解决方案?
  • 已扩展答案以添加正确的逻辑。您不应在一次迭代中调用 next() 两次。
  • 我编辑了代码。我没有得到任何异常,但代码不起作用。我错过了一些关键的东西!
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    • 2021-01-17
    • 2015-04-23
    • 2022-01-21
    相关资源
    最近更新 更多