【问题标题】:Regarding Object Comparison关于对象比较
【发布时间】:2010-02-23 02:55:24
【问题描述】:

我有一个 java 类 Rec。我有 Rec1 和 Rec2 的两个实例。我想检查 Rec1 和 Rec2 的值是否相等。如果我做 Rec1.equals(Rec2) 是正确的做法吗?

class Rec {

  private BigDecimal  RecordId = null; 

  private BigDecimal recSubNum = null; 

  private BigDecimal  FileId = null;

  private String    Category = null; 

  private BigDecimal status = null; 

  private BigDecimal errorCode = null; 

} 

【问题讨论】:

    标签: java class


    【解决方案1】:

    您需要实现equals()hashCode() 方法以在Java 中实现对象相等:

    class Rec {
      private BigDecimal recordId = null;
      private BigDecimal recSubNum = null;
      private BigDecimal FileId = null;
      private String category = null;
      private BigDecimal status = null;
      private BigDecimal errorCode = null;
    
      @Override
      public int hashCode() {
        int ret = 41;
        ret = hc(ret, recordId);
        ret = hc(ret, recSubNum);
        ret = hc(ret, fieldId);
        ret = hc(ret, category);
        ret = hc(ret, status);
        ret = hc(ret, errorCode);
        return ret;
      }
    
      @Override
      public boolean equals(Object ob) {
        if (ob == null) return false;
        if (ob.getClass() != Rec.class) return false;
        Rec r = (Rec)ob;
        if (!eq(r.recordId, record)) return false;
        if (!eq(r.recSubNum, recSubNum)) return false;
        if (!eq(r.fileId, fileId)) return false;
        if (!eq(r.category, category)) return false;
        if (!eq(r.status, status)) return false;
        if (!eq(r.errorCode, errorCode)) return false;
        return true;
      }
    
      private static boolean eq(Object ob1, Object ob2) {
        return ob1 == null ? ob2 == null : ob1.equals(ob2);
      }
    
      private static int hc(int hc, Object field) {
        return field == null ? hc : 43 + hc * field.hashCode();
      }
    }
    

    注意:Java 的 equals/hashCode 约定意味着对于任意两个对象 a 和 b:

    a.equals(b) == b.equals(a)
    

    如果两个对象相等,则a.hashCode() 必须等于b.hashCode()

    编辑:检查类型是否匹配有两种方法。要么:

    if (ob == null) return false;
    if (ob.getClass() != Rec.class) return false;
    

    if (!(ob instanceof Rec)) return false;
    

    这两个做不同的事情,你应该根据你想做的事情选择正确的一个。我通常更喜欢第一个,除非你知道你需要第二个。有什么区别?

    class A {
      public int i;
    
      public boolean equals(Object ob) {
        if (!(ob instanceof A)) return false;
        return i == ((A)ob).i;
      }
    }
    

    看起来很合理吧?如果类被扩展怎么办:

    class B extends A {
      public int j;
    
      public boolean equals(Object ob) {
        if (!(ob instanceof B)) return false;
        if (!super.equals(ob)) return false;
        return j == ((B)ob).j;
      }
    }
    

    看起来仍然合理吗?坏了。

    A a = new A();
    a.i = 10;
    B b = new B();
    b.i = 10;
    b.j = 20;
    System.out.println(a.equals(b)); // true! Is this really what you want?
    System.out.println(b.equals(a)); // false! Different to previous = problem.
    

    这就是为什么我更喜欢getClass() 而不是instanceof,除非我真的想要子类平等。

    【讨论】:

    • @arav,这是您可能想阅读的相关文章:javapractices.com/topic/TopicAction.do?Id=17@cletus +1 以获得完整答案:)
    • 这很好用,但是来自 apache lang commons.apache.org/lang 的 Apache EqualsBuilder 和 HashCodeBuilder 使这变得微不足道。
    • +1,为此欢呼——我不知道存在的东西。将来可能与我的兴趣相关:)
    • 合约还包括两个对象应该是同一个具体类,并且 o.equals(null) == false 如果传递一个空值,此注释中的代码将抛出 NullPointerException。 Apache EqualsBuilder 和 HashCodeBuilder 确实让它变得简单,但您仍然需要进行类匹配和空值检查。
    • @rjohnston:instanceof 有问题。查看更新。
    【解决方案2】:

    如果 Rec 是一个用户定义的类,那么你真的应该重写 equals 方法,否则它只会调用 Object 类中的 equals 方法;

    类似:

    public boolean equals(Rec x){
        //check here to see if the references are the same, if so return true
        if(this == x) return true;
    
        //if they aren't the same object then check all the fields for equality
        if (category.equals(x.category) && etc etc) return true;
        else return false;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-04
      • 1970-01-01
      • 2013-11-01
      相关资源
      最近更新 更多