Используйте 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
, но это означает, что два объекта могут считаться равными, даже если они принадлежат разным классам, если они имеют одинаковый идентификатор. Есть ли другой путь?
3 ответа
Вы можете использовать динамическую версию instanceof
оператор, который Class
"s isInstance
метод.
Определяет, является ли указанный Объект совместимым с назначением с объектом, представленным этим Классом.
if (!(getClass().isInstance(other))) return false;
Это не помешает экземпляру подкласса протестировать equals
на объекте суперкласса, но динамический способ гарантировать, что это точно такой же класс, будет сравнивать два Class
объекты для равенства.
if (!(getClass().equals(other.getClass()))) return false;
Мне нравится ответ rgetmann /questions/5856896/ispolzujte-instanceof-ne-znaya-tipa/5856911#5856911 но он неполный. Я думаю, что приведенный ниже код (никоим образом не проверен) завершает его.
boolean equals(Object b){
return getClass().equals(b.getClass())
&& id==getClass().cast(b).id;
}
Вы можете иметь суперкласс с методом 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()
метод для каждого вашего класса.