2016-02-08 33 views
10

Meine Java-Klassen stellen Entitäten innerhalb einer Datenbank dar, und ich finde es praktisch, die equals-Methode meiner Klassen zu überschreiben, um Vergleiche anhand der ID durchzuführen. So zum Beispiel in meiner Transaction Klasse habe ich dieses Stück CodeVerwenden Sie instanceof, ohne den Typ zu kennen

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

Jetzt ist es ein bisschen hässlich ich scheint, dass jede Klasse das gleiche Stück Code hält, nur mit dem Namen der Klasse geändert. Ich dachte darüber nach, meine Klassen erweitern eine Superklasse MyEntity, wo ich die obige Methode schreiben würde, ersetzen instanceof Transaction mit etwas wie instanceof this.getClass(), aber dies scheint nicht möglich zu sein. Ich dachte auch darüber nach, es durch instanceof MyEntity zu ersetzen, aber das bedeutet, dass zwei Objekte als gleich angesehen werden können, auch wenn sie zu verschiedenen Klassen gehören, solange sie dieselbe ID haben. Gibt es einen anderen Weg?

Antwort

6

Sie können die dynamische Version des instanceof-Operators verwenden, der ClassisInstance Methode ist.

Bestimmt, ob das angegebene Objekt mit dem von dieser Klasse dargestellten Objekt zuweisungskompatibel ist. Diese

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

nicht eine Instanz einer Unterklasse verhindern Testen equals auf einem Super Objekt, sondern eine dynamische Art und Weise zu gewährleisten, dass es genau die gleiche Klasse ist, die beide Class Objekte auf Gleichheit zu vergleichen wäre.

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

Für diese Anwendung scheint die zweite Methode, die die gleiche Klasse erfordert, am besten geeignet. – erickson

+1

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

1

Sie können eine Super-Klasse mit einer Equals-Methode haben.

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

} 

Und dann kann man es in jedem Ihrer Klasse diese Weise verwenden:

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

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

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

Vorteile:
+ Sie Code-Duplizierung in jeder Klasse vermeiden.
+ Alle Typen werden unterstützt.
+ Keine Abgüsse mehr.

Nachteile:
- Sie müssen getId() und getEntityClass() Methode für jede Ihrer Klasse definieren.

+1

Korrigiert, danke mate;) –

+0

Wäre es Fälle, in denen 'getEntityClass() 'etwas anderes zurückgibt als' getClass() '? Wie siehst du das benutzt wird? – erickson

+0

Hier ist die Schwäche, Sie müssen vorsichtig sein, wenn Sie die Funktion überschreiben. Ich kann den Code nicht in die Schnittstelle einfügen, oder die CSS wäre die Schnittstelle selbst, also ...Aber der generische Typ ENTITY beschränkt Typen, die von ComparablebyId erben –

1

Ich mag Rgetmanns Antwort https://stackoverflow.com/a/35280674/348975 aber es ist unvollständig. Ich denke, der unten stehende Code (in keiner Weise getestet) vervollständigt es.

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