在不知道类型的情况下使用 instanceof

Use instanceof without knowing the type

我的 Java classes 表示数据库中的实体,我发现重写 classes 的 equals 方法以按 id 进行比较很实用.因此,例如在我的 Transaction class 中,我有这段代码

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

现在对我来说有点丑陋,每个 class 都包含相同的代码段,只是 class 的名称发生了变化。我想过让我的 classes 扩展一个 superclass MyEntity,我会在其中编写上述方法,用 instanceof this.getClass() 之类的东西替换 instanceof Transaction,但这并没有似乎是可能的。我也考虑过用 instanceof MyEntity 替换它,但这意味着即使两个对象属于不同的 class,只要它们具有相同的 id,也可以认为它们是相等的。 还有其他办法吗?

您可以使用 instanceof 运算符的动态版本,即 ClassisInstance 方法。

Determines if the specified Object is assignment-compatible with the object represented by this Class.

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

这不会阻止 subclass 的实例在 superclass 对象上测试 equals,而是一种确保它完全相同的动态方法 class 将比较两个 Class 对象是否相等。

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

你可以有一个超级 class 和 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());
    }

}

然后你可以用这种方式在你的所有 class 中使用它:

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

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

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

好处:
+ 避免每个 classes.
中的代码重复 + 支持所有类型。
+ 没有更多演员。

缺点:
- 您需要为每个 class.

定义 getId()getEntityClass() 方法

我喜欢 rgetmann 的回答 但它不完整。我认为下面的代码(没有以任何方式测试)完成了它。

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