2016-02-08 2 views
10

Мои классы Java представляют собой сущности внутри базы данных, и я считаю целесообразным переопределить метод моих классов, чтобы сделать сравнения по id. Так, например, в моем Transaction классе у меня есть этот кусок кодаИспользуйте instanceof, не зная тип

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

Теперь это кажется немного некрасиво мне, что каждый класс имеет один и тот же кусок кода, только имя класса изменился. Я думал о том, чтобы мои классы расширяли суперкласс MyEntity, где я бы написал вышеописанный метод, заменив instanceof Transaction чем-то вроде instanceof this.getClass(), но это не представляется возможным. Я также подумал о замене его на instanceof MyEntity, но это означает, что два объекта можно считать равными, даже если они принадлежали к разным классам, если они имеют одинаковый идентификатор. Есть ли другой способ?

ответ

6

Вы можете использовать динамическую версию оператора instanceof, который составляет ClassisInstance.

Определяет, является ли указанный объект совместимым с объектом с объектом, представленным этим классом.

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

Это не помешает экземпляр подкласса от тестирования equals на суперкласс объекта, а динамический способ гарантировать, что это тот же самый класс был бы сравнить два Class объектов равенства.

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

Для этого приложения наиболее подходящим является второй метод, который требует того же класса. – erickson

+1

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

1

Вы можете иметь суперкласс с равным методом.

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

} 

И тогда вы можете использовать его во всех из вашего класса таким образом:

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

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

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

Преимущества:
+ позволяет избежать дублирования кода в каждом классе.
+ Все типы одобрены.
+ Больше никаких отливок.

Минусы:
- Вам нужно определить getId() и getEntityClass() метод для каждого из вашего класса.

+1

Исправлено, спасибо mate;) –

+0

Будут случаи, когда 'getEntityClass()' возвращает что-то, кроме 'getClass() '? Как вы видите, что это используется? – erickson

+0

Вот слабость, вам нужно быть осторожным, когда вы переопределяете функцию. Я не могу поместить код в интерфейс, или calss будут самим интерфейсом, поэтому ...Но типы ограничения типа ENTITY, которые наследуются от ComparablebyId –

1

Мне нравится ответ rgetmann https://stackoverflow.com/a/35280674/348975, но он неполный. Я думаю, что приведенный ниже код (ни в коем случае не проверенный) не завершает его.

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