Domanda

Proverò a spiegare il mio problema nel modo più chiaro possibile :). Sto usando PropertyChangeSupport per notificare le viste registrate per i cambiamenti nelle proprietà. Una delle proprietà è un oggetto le cui proprietà vengono modificate ogni vista secondi. Non voglio creare per questo particolare oggetto una nuova istanza ogni volta che viene aggiornato (perché il listener di proprietà noti la modifica), quindi ho scritto il mio metodo uguale dove ommetto il confronto con se stesso.

@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;
}

Sfortunatamente questo non ha l'effetto che stavo cercando. Se creo una copia dell'oggetto e utilizzo il metodo di modifica della proprietà su di esso, allora funziona perfettamente.

Cosa mi sto perdendo qui?

- Modifica

Mi sono reso conto che dal momento che sto usando la stessa istanza e non una sua copia, le proprietà sono puntate nello stesso posto, quindi il confronto sarebbe sempre vero. C'è una soluzione alternativa a questo (oltre a creare una copia). O quanto è male creare una copia di un oggetto ogni secondo, ad es.

È stato utile?

Soluzione

Devi sempre restituire true per dire a PropertyChangeSupport che l'oggetto non è cambiato. Ciò significa che equals () è rotto per tutti gli oggetti di questa classe (quindi non puoi più usarli in set o mappe, per esempio).

Un modo migliore sarebbe quello di avere un metodo speciale firePropertyChange () per questo tipo di oggetto che esegue la gestione speciale. In questo modo, puoi anche evitare di creare un'istanza di PropertyChangeEvent . Ecco un esempio per la gestione di BigDecimal (dove equals () non funziona affatto):

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));
}

[EDIT] Ciò che fai è completamente diverso: hai un genitore e un figlio e desideri che gli ascoltatori del genitore ricevano eventi quando il figlio cambia.

L'approccio corretto qui è quello di aggiungere PropertyChangeSupport al figlio . Quando il figlio viene aggiunto al genitore, il genitore deve installare i listener necessari nel figlio. Quando un evento viene generato, deve generare un secondo evento che informa gli ascoltatori del genitore della modifica nel figlio (il genitore deve inoltrare gli eventi).

Altri suggerimenti

questo è un caso di agenti di scambio di proprietà concatenati:

TransferQueueItem dovrebbe avviare i propri PropertychangeEvents che devono essere ascoltati da TransferQueue in cui è inserito

E in risposta TransferQueue deve informare i propri ascoltatori che un oggetto di proprietà è cambiato.

Ogni volta che ho un problema come questo in cui un oggetto deve riavviare eventi utilizzo questa convenzione (del mio team di lavoro):

1 Un oggetto può solo lanciare eventi la cui fonte è essa stessa.

2 Se desidera un evento delegato, avvia un evento come questo: new PropertyChangeEvent (questo, " DELEGATED_EVENT " ;, null, ricevutoEvent). In modo che gli ascoltatori possano seguire la catena di eventi.

In aggiunta ho un metodo statico in una classe Util che segue la catena di eventi e restituisce il primo evento, l'unica proprietà whick non è " DELEGATED_EVENT "

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top