【问题标题】:Use instanceof without knowing the type在不知道类型的情况下使用 instanceof
【发布时间】:2016-05-18 18:16:57
【问题描述】:

我的 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 替换它,但这意味着两个对象即使属于不同的类也可以被认为是相等的,只要它们具有相同的ID。 有没有其他办法?

【问题讨论】:

    标签: java instanceof dynamic-typing


    【解决方案1】:

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

    确定指定的对象是否与该类表示的对象分配兼容。

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

    这不会阻止子类的实例在超类对象上测试 equals,但确保它是完全相同的类的动态方法是比较两个 Class 对象是否相等。

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

    【讨论】:

    • 对于这个应用程序,需要相同类的第二种方法似乎最合适。
    • if( this.getClass()!=that.getClass() ) ... :)
    【解决方案2】:

    我喜欢 rgetmann 的回答 https://stackoverflow.com/a/35280674/348975,但它不完整。我认为下面的代码(未经任何测试)完成了它。

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

    【讨论】:

      【解决方案3】:

      你可以拥有一个带有 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() 方法。

      【讨论】:

      • 会有getEntityClass()返回getClass()以外的东西的情况吗?您如何看待它的使用?
      • 这里是弱点,重写函数时需要小心。我不能将代码放在接口中,否则 calss 将是接口本身,所以...但是 ENTITY 泛型类型限制从 ComparablebyId 继承的类型
      • 你不能覆盖getClass(),所以如果你的默认equals()实现使用getClass()而不是getEntityClass(),它不会产生相同的结果吗?
      • 我不确定我是否理解你的问题,我试图在界面中分解equals 方法。所以你不再需要定义`equals方法,所以......我想我不明白你的问题
      • 嗯,看起来default 方法无法覆盖来自Object 的方法。你能编译这个吗?
      猜你喜欢
      • 2018-07-08
      • 2012-09-19
      • 1970-01-01
      • 2013-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多