【问题标题】:PropertyChangeSupport and equals methodPropertyChangeSupport 和 equals 方法
【发布时间】:2009-10-22 08:29:40
【问题描述】:

我会尽可能清楚地解释我的问题:)。我正在使用 PropertyChangeSupport 通知已注册视图的属性更改。其中一个属性是一个对象,该对象的属性在每个视图秒内都会更改。我不想在每次更新时为这个特定对象创建新实例(让 propertychangelistener 注意到变化),所以我编写了自己的 equals 方法,我省略了与自身的比较。

@Override
public boolean equals(Object item) {
    // do not compare 
    // if (this == item) { return true; }

    if (!(item instanceof TransferQueueItem) || 
        item == null) {

        return false;
    }

    TransferQueueItem newItem = (TransferQueueItem) item;
    boolean value = 
            // ommited... properties comparation
    return value;
}

很遗憾,这并没有达到我想要的效果。如果我创建对象的副本并在其上触发属性更改方法,那么它可以正常工作。

我在这里错过了什么?

-- 编辑

我意识到,因为我使用的是同一个实例而不是它的副本,所以属性指向同一个地方,因此比较总是会成立。是否有解决方法(除了创建副本)。或者每秒创建一个对象的副本有多糟糕,例如。

【问题讨论】:

  • 这无关紧要,因为对同一实例的任何更改都应该向该实例的所有侦听器触发事件​​。您在这里省略了一些重要信息。

标签: java equals javabeans propertychangesupport


【解决方案1】:

您必须始终返回true 以告诉PropertyChangeSupport 您的对象没有发生了变化。但这意味着 equals() 对于此类的所有对象都已损坏(例如,您不能再在集合或地图中使用它们)。

更好的方法是为这种进行特殊处理的对象使用特殊方法firePropertyChange()。这样,您甚至可以避免创建PropertyChangeEvent 的实例。这是处理BigDecimal 的示例(其中equals() 根本不起作用):

protected transient PropertyChangeSupport changeSupport = null;

public void addPropertyChangeListener (String propertyName, PropertyChangeListener listener)
{
    if (changeSupport == null)
        changeSupport = new PropertyChangeSupport (this);

    changeSupport.addPropertyChangeListener (propertyName, listener);
}

public void firePropertyChange (String propertyName, BigDecimal oldValue, BigDecimal newValue)
{
    if (changeSupport == null)
        return;

    if (oldValue != null && newValue != null && oldValue.compareTo (newValue) == 0) {
        return;
    }
    changeSupport.firePropertyChange(new PropertyChangeEvent(this, propertyName,
                                               oldValue, newValue));
}

[编辑] 你所做的完全是另外一回事:你有一个父母和一个孩子,并且你希望 父母 的侦听器在 孩子 发生变化时接收事件。

这里正确的做法是将PropertyChangeSupport添加到child。将子级添加到父级时,父级必须在子级中安装必要的侦听器。当一个事件被触发时,它必须触发第二个事件,通知 parent 的侦听器 child 的变化(父母必须转发事件)。

【讨论】:

  • 其实我想要的恰恰相反。并且总是返回硬编码值并不完全是 equals 应该是什么。
  • 在这种情况下,您的问题不清楚。您想避免因对 TransferQueueItem 的任何更改而触发事件吗?当 TransferQueueItem 更改时,您是否总是想要一个事件?当 TransferQueueItem 的属性发生变化时,您是否总是想要一个事件?
  • 请注意,设置新的 TransferQueueItem 或更改 TransferQueueItem 的属性是不同的。
  • 每次 TransferQueueItem 改变时我都想要一个事件,但是 TransferQueueItem 只是 TransferQueue 的一个属性,所以它不是触发事件的那个。
  • 监听器将自己添加到 TransferQueue 对象中,该对象也是触发 propertychange 事件的对象。
【解决方案2】:

这是一个链式propertychangelisteners的例子:

TransferQueueItem 应该启动它们自己的 PropertychangeEvents,它必须被插入的 TransferQueue 监听

作为响应,TransferQueue 必须通知其侦听器拥有的项目已更改。

每当我遇到对象必须重新启动事件的此类问题时,我都会使用这个约定(我的工作团队的):

1 对象只能启动其来源为自身的事件。

2 如果它想要委托事件,它会启动如下事件:new PropertyChangeEvent(this,"DELEGATED_EVENT", null, receivedEvent)。这样听众就可以跟踪事件链。

另外,我在 Util 类中有一个静态方法,它遵循事件链并返回第一个事件,其中一个属性不是“DELEGATED_EVENT”

【讨论】:

  • 感谢指点!以这种方式实现它确实很有意义。
猜你喜欢
  • 2013-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-27
  • 2015-09-09
相关资源
最近更新 更多