Использовать instanceof без знания типа
Мои классы Java представляют собой сущности внутри базы данных, и я считаю целесообразным переопределить метод equals
моих классов, чтобы сделать сравнения по id. Так, например, в моем классе Transaction
у меня есть этот фрагмент кода
@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
, но это означает, что два объекта можно считать равными, даже если они принадлежат к разным классам, если они имеют одинаковый идентификатор.
Есть ли другой способ?
Ответы
Ответ 1
Вы можете использовать динамическую версию оператора instanceof
, который является Class
isInstance
.
Определяет, является ли указанный объект совместимым с объектом с объектом, представленным этим классом.
if (!(getClass().isInstance(other))) return false;
Это не помешает экземпляру подкласса тестировать equals
на объекте суперкласса, но динамический способ убедиться, что он точно такой же класс будет сравнивать два объекта Class
для равенства.
if (!(getClass().equals(other.getClass()))) return false;
Ответ 2
У вас может быть суперкласс с методом equals.
// 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()
для каждого из ваших классов.
Ответ 3
Мне нравится rgetmann answer fooobar.com/info/556427/..., но он неполный. Я думаю, что приведенный ниже код (никоим образом не протестированный) не завершает его.
boolean equals(Object b){
return getClass().equals(b.getClass())
&& id==getClass().cast(b).id;
}