método PropertyChangeSupport e equals
-
05-07-2019 - |
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.
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"