PropertyChangeSupportおよびequalsメソッド
-
05-07-2019 - |
質問
できるだけ明確に問題を説明しようと思います:)。 PropertyChangeSupportを使用して、登録されたビューにプロパティの変更を通知します。プロパティの1つは、表示秒ごとにプロパティが変更されるオブジェクトです。更新されるたびに(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;
}
残念ながら、私が探していた効果はありません。オブジェクトのコピーを作成し、そのオブジェクトでプロパティ変更メソッドを実行すると、正常に機能します。
ここで不足しているものは何ですか?
-編集
私は、同じインスタンスを使用しており、そのコピーではないため、プロパティが同じ場所を指しているため、比較が常に真になることを認識しました。それに対する回避策はありますか(コピーの作成以外)。または、オブジェクトのコピーを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 に追加することです。子が親に追加されると、親は必要なリスナーを子にインストールする必要があります。イベントが発生すると、子の変更を親のリスナーに通知する2番目のイベントを発生する必要があります(親はイベントを転送する必要があります)。
他のヒント
これはチェーンされたpropertychangelistenersの場合です:
TransferQueueItemは、独自のPropertychangeEventsを起動する必要があります。これは、挿入されたTransferQueueでリッスンする必要があります
応答で、TransferQueueは所有アイテムが変更されたことをリスナーに通知する必要があります。
このような問題が発生するたびに、オブジェクトがイベントを再起動する必要があるため、(私の作業チームの)この規則を使用します:
1オブジェクトは、ソース自体のイベントのみを起動できます。
2デリゲートイベントが必要な場合、new PropertyChangeEvent(this、" DELEGATED_EVENT&quot ;, null、receivedEvent)のようなイベントを起動します。これにより、リスナーは一連のイベントを追跡できます。
さらに、Utilクラスに静的なメソッドがあり、イベントチェーンをたどって最初のイベントを返しますが、その1つは「DELEGATED_EVENT」ではありません