Pergunta

Eu vou tentar explicar o meu problema tão clara quanto possível :). Eu estou usando PropertyChangeSupport para notificar vistas registrados para mudanças nas propriedades. Uma das propriedades é um objeto cujas propriedades são mudadas a cada vista segundos. Eu não quero criar para este novo objeto instância específica de cada vez que está sendo atualizado (para o PropertyChangeListener para notar a mudança), então eu escrevi o meu próprio método equals onde eu omitir a comparação de si mesmo.

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

Infelizmente que não tem o efeito que eu estava procurando. Se eu criar uma cópia do objeto e disparar o método de mudança de propriedade sobre ele, então ele funciona bem.

O que estou ausente aqui?

- Edit

Eu percebi, que desde que eu estou usando o mesmo exemplo e não uma cópia do mesmo, as propriedades são pointig mesmo lugar, portanto, a comparação sempre sairiam verdade. Existe uma solução para isso (além de criar uma cópia). Ou o quão ruim é criar uma cópia de um objeto a cada segundo, por exemplo.

Foi útil?

Solução

Você deve sempre retornar true para dizer PropertyChangeSupport que seu objeto fez não mudança. Mas isso significa que equals() é dividido para todos os objetos desta classe (assim você não pode usá-los em conjuntos ou mapeia mais, por exemplo).

A melhor maneira seria ter um firePropertyChange() método especial para este tipo de objeto que faz o tratamento especial. Dessa forma, você pode até mesmo evitar criar uma instância de PropertyChangeEvent também. Aqui está um exemplo para lidar com BigDecimal (onde equals() não funciona em todos):

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] O que você faz é algo completamente diferente: Você tem um pai e um filho e você quer ouvintes da pai para receber eventos quando o criança mudanças.

A abordagem correta aqui é adicionar PropertyChangeSupport para a criança . Quando o filho é adicionado para o pai, o pai deve instalar os ouvintes necessárias na criança. Quando um evento é acionado, ele deve disparar um segundo evento que informa os ouvintes da pai da mudança no criança (o pai deve encaminhar os eventos).

Outras dicas

este é um caso de propertychangelisteners encadeadas:

TransferQueueItem deve lançar seus próprios PropertychangeEvents que deve ser escutado pela TransferQueue em que se insere

E em resposta TransferQueue deve notificar os seus ouvintes que um item de propriedade mudou.

Toda vez que tenho um problema como este em que um objeto deve relançar eventos i utilizar esta convenção (da minha equipe de trabalho):

1 Um objeto só pode lançar eventos qual a fonte em si é.

2 Se quiser evento delegado que inaugura um evento como este: new PropertyChangeEvent (this, "DELEGATED_EVENT", null, receivedEvent). Assim que os ouvintes podem seguir a cadeia de eventos.

Addicionally eu tenho um método estático em uma classe Util que seguem a cadeia de eventos e retorna o primeiro evento, o whick propriedade não é "DELEGATED_EVENT"

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top