我会尽可能清楚地解释我的问题:)。我正在使用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;
}
不幸的是,这没有我想要的效果。如果我创建了一个对象的副本并在其上触发属性更改方法,那么它可以正常工作。
我在这里缺少什么?
- 编辑
我意识到,既然我使用相同的实例而不是它的副本,那么属性就是指向相同的位置,因此比较总是真实的。是否有解决方法(除了创建副本)。或者每秒创建一个对象副本有多糟糕,例如
答案 0 :(得分: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
添加到子。将子项添加到父项时,父项必须在子项中安装必要的侦听器。触发事件时,它必须触发第二个事件,该事件通知侦听器父 子中的更改(父事件必须转发事件)。
答案 1 :(得分:1)
这是一个链式propertychangelisteners的案例:
TransferQueueItem应该启动自己的PropertychangeEvents,必须由插入的TransferQueue监听
作为回应,TransferQueue必须通知其听众已拥有的项目已更改。
每次我遇到这样的问题,其中一个对象必须重新启动事件我使用这个约定(我的工作团队):
1对象只能启动源本身的事件。
2如果它想要委托事件,它会启动一个这样的事件:new PropertyChangeEvent(this,“DELEGATED_EVENT”,null,receivedEvent)。这样听众就可以跟随事件链。
Addicionally我在Util类中有一个静态方法,它遵循事件链并返回第一个事件,一个whick属性不是“DELEGATED_EVENT”