关于在Java中重写equals方法

4

我尝试在一个类中覆盖equals和hashcode方法。这个类是另一个没有实现equals方法和hashCode方法的类的子类。

Eclipse给出了以下警告:

  The super class ABC does not implement equals() and hashCode() methods.
  The resulting code may not work correctly. 

为什么会出现上述警告?在什么情况下,它可能无法正常工作?

2
一个很好的概述:http://www.artima.com/lejava/articles/equality.html - Michael Brewer-Davis
2个回答

5
如果你写了 a.equals(b) 或者 b.equals(a),那么它们的行为应该是相同的,前提是它们都是相应类型的对象 BA,并且只有其中一个正确实现了 equals 方法。如果我们假设 A 是父类并且没有实现 equals 方法(所以它继承自java.lang.Object.equals),而子类 B 覆盖了 equals 方法并依赖于 name 字段,则这两个例子的行为会有所不同。
class A {

  String name;

  public A() {
    this.name = "Fred";
  }

}

class B extends A {

  public boolean equals(Object o) {
    A a = (A)o;
    return a != null && a.name.equals(this.name);
  }
}

public class Test {

  public static void main(String[] args) {

    A a = new A();
    B b = new B();

    System.out.println(a.equals(b) == b.equals(a));
  }
} 

不出所料,输出结果为false,因此破坏了对称性


我不同意。你能构造一个例子来证明如果超类没有实现“equals”,对称性可以被打破吗?我相当确定警告信息是无效的。我见过的每个破坏对称性的例子都需要超类定义“equals”。 - Duncan Jones
嗯...其实并不是这样的。为什么B类中的equals方法要将对象转换为A呢?别误会了——确实可能会出现打破对称性的示例,但我见过的每个示例都有(故意的)重大缺陷。 - Duncan Jones
请参考以下相关问题:https://dev59.com/8WQo5IYBdhLWcg3wMtC2当超类没有重新声明equals和hashCode会发生什么错误 - Duncan Jones
@DuncanJones - 根据您在其他问题中的评论:超类没有equals方法。因此,您的所有示例都不相关。 所有类都有一个equals方法 - 有时它们继承它,有时(因此)它是错误的。 - Daniel Earwicker
关于您的第一个问题 - 是的,除非超类覆盖equals方法,否则我还没有看到我认为是“真正”的对称性问题。文献中的经典示例都是在超类覆盖equals方法时触发的。 - Duncan Jones
显示剩余4条评论

0

你尝试过在超类中重写equals方法,然后自动生成子类的重写实现吗?我相信它会有所不同,它将调用super.equals()。在当前自动生成的实现中,它只检查子类中的值。考虑下面的场景,你就会明白为什么会出现警告。

abstract Class A{
 private int a;
public void setA(int a){
this.a=a;
}
}

Class B extends A{
 private int x;
public void setX(int x){
this.x=x;
}

@Override
public boolean equals(Object obj) { // This does not call Super.equals
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    B other = (B) obj;
    if (x != other.x)
        return false;
    return true;
}

}

在主方法中尝试

B b1= new B();
b1.setA(10);
b1.setX(20);


B b2= new B();
b2.setA(20);
b2.setX(20);

if(b1.equals(b2)){
 System.out.println("Warning was Right");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接