2016-02-08 9 views
10

Le mie classi Java rappresentano entità all'interno di un database e trovo pratico sovrascrivere il metodo equals delle mie classi per fare confronti con id. Così, per esempio nella mia classe Transaction ho questo pezzo di codiceUtilizzare instanceof senza conoscere il tipo

@Override 
public boolean equals(Object other){ 
    if (other == null) return false; 
    if (other == this) return true; 
    if (!(other instanceof Transaction))return false; 
    Transaction otherTrans = (Transaction) other; 
    if (id == null || otherTrans.id == null) return false; 
    return id.equals(otherTrans.id); 
} 

Ora sembra un po 'brutto per me che ogni classe contiene lo stesso pezzo di codice, con il solo nome della classe cambiato. Ho pensato di rendere le mie classi estendere una superclasse MyEntity dove scriverei il metodo sopra, sostituendo instanceof Transaction con qualcosa come instanceof this.getClass(), ma questo non sembra possibile. Ho anche pensato di sostituirlo con instanceof MyEntity, ma ciò significa che due oggetti potrebbero essere considerati uguali anche se appartenessero a classi diverse, purché abbiano lo stesso id. C'è qualche altro modo?

risposta

6

È possibile utilizzare la versione dinamica dell'operatore instanceof, che è il metodo Class.

Determina se l'oggetto specificato è compatibile con l'oggetto rappresentato da questa classe.

if (!(getClass().isInstance(other))) return false; 

Questo non impedirà un'istanza di una sottoclasse da testare equals su un oggetto superclasse, ma un modo dinamico di garantire che sia la stessa classe esatto sarebbe di confrontare i due Class oggetti in parità.

if (!(getClass().equals(other.getClass()))) return false; 
+0

Per questa applicazione, il secondo metodo che richiede la stessa classe sembra il più appropriato. – erickson

+1

o 'if (this.getClass()! = That.getClass())' ... :) – ZhongYu

1

È possibile avere una super classe con un metodo uguale.

// Where ENTITY would be the type of the class to compare, and ID the type of the id 
public abstract class ComparableById<ENTITY extends ComparableById, ID> { 

    protected abstract Class<?> getEntityClass(); 
    protected abstract ID getId(); 

    @Override 
    public boolean equals(Object other) { 
     if (other == null) return false; 
     if (other == this) return true; 
     if (!getEntityClass().isInstance(other)) return false; 
     ComparableById o = (ComparableById) other; 
     if (getId() == null || o.getId() == null) return false; 
     return getId().equals(o.getId()); 
    } 

} 

E poi si può utilizzare in tutta la vostra classe in questo modo:

@Entity 
public class TeacherEntity extends ComparablebyId<TeacherEntity, Long> { 
    private Long id; 

    @Override 
    public Long getId() { 
     return this.id; 
    } 

    @Override 
    public getEntityClass() { 
     return this.getClass(); 
    } 
} 

Vantaggi:
+ Evitate la duplicazione del codice in ogni classe.
+ Tutti i tipi sono supportati.
+ Niente più lanci.

Contro:
- è necessario definire il metodo getId() e getEntityClass() per ciascuna della classe.

+1

Risolto, grazie amico;) –

+0

Ci sarebbero casi in cui 'getEntityClass()' restituisce qualcosa di diverso da 'getClass() '? Come vedi che viene usato? – erickson

+0

Ecco la debolezza, è necessario essere attenti quando si sostituisce la funzione. Non riesco a inserire il codice nell'interfaccia, o il calss sarebbe l'interfaccia stessa, quindi ...Ma il tipo generico ENTITY limita i tipi che ereditano da ComparablebyId –

1

Mi piace la risposta di rgetmann https://stackoverflow.com/a/35280674/348975 ma è incompleto. Penso che il codice sottostante (non in alcun modo testato) lo completi.

boolean equals(Object b){ 
    return getClass().equals(b.getClass()) 
       && id==getClass().cast(b).id; 
} 
Problemi correlati