Java 重写了超类Equals和HashCode,并认为应该对子类执行同样的操作

Java 重写了超类Equals和HashCode,并认为应该对子类执行同样的操作,java,equals,hashcode,Java,Equals,Hashcode,我有一个带有2个变量(inta)(intb)的超类,还有一个子类,它通过使用子类中现有的改进方法覆盖2个超类方法来扩展超类的功能。作为我的子类的一部分,我现在有了一个新的int(intc),它是一个唯一的id(UUID) 我理解用equals方法很难保持平等 我是否可以覆盖超类equals和hashCode方法以显示相等,并根据上述情况对子类equals和hashCode方法执行相同操作 我最初重写了超类中的equals和hashCode方法。如果由于子类中的额外实例变量(int c)也应该对子

我有一个带有2个变量(
inta
)(
intb
)的超类,还有一个子类,它通过使用子类中现有的改进方法覆盖2个超类方法来扩展超类的功能。作为我的子类的一部分,我现在有了一个新的
int
intc
),它是一个唯一的id(UUID)

我理解用
equals
方法很难保持平等

我是否可以覆盖超类
equals
hashCode
方法以显示相等,并根据上述情况对子类
equals
hashCode
方法执行相同操作

我最初重写了超类中的
equals
hashCode
方法。如果由于子类中的额外实例变量(
int c
)也应该对子类执行此操作。我知道应该有一个
hashCode
方法来显示这一点,我读到如果
haschCode
被更改,那么子类的
equals
方法必须更改吗

我真的不知道该怎么做才是最好的

我想知道我的超类
equals
hashCode
方法是否可以显示相等关系?是否允许子类与我的超类
equals
hashCode
重写方法一起显示
inta
intb
intc
的相等比较,以及子类的
hashCode
方法更新以显示
int
s
a
的唯一hashCode>,
b
c

我正在考虑比较超类
equals
方法中的
int
s
a
b
并更新这两个变量的hashcode,以及
equals
方法中的
int
s
a
b
c
更新这三个变量的hashcode。只是超类中的
intc
是唯一的

非常感谢这里的任何建议,因为我相信忽略和不处理子类
equals
hashCode
方法中的
int c
可能是不可能的


提前感谢

基本上,您有两种可能的选择:

  • 完全忽略
    c
    。根据
    a
    b
    定义超类的相等性,不要在子类中重写它

  • 始终将超类和子类的实例视为不相等。它允许您在超类(基于
    a
    b
    )和子类(基于
    a
    b
    c
    )中以不同的方式定义相等性

    请注意,在这种情况下,在子类中重写
    equals()
    hashcode
    是不够的-在实现超类的
    equals()
    方法时,还需要一个特殊的技巧,请参阅中关于
    canEquals()
    方法的部分


  • 你的问题的关键是你是否希望你的超类的一个实例和你的子类的一个实例能够相等地进行比较

    如果是这样,请不要重写
    equals()
    hashCode()
    方法。您甚至可以在超类中将它们设置为
    final

    如果不是,则每个类的
    equals()
    方法应使用
    getClass()
    ,而不是
    instanceof
    检查
    equals()
    的参数类型。例如,在超类中:

    if ((obj == null) || (!getClass().equals(obj.getClass()))
      return false;
    /* Compare a and b. */
    ...
    
    在子类中:

    if (!super.equals(obj))
      return false;
    /* Compare c. */
    ...
    
    如果哈希代码基于
    a
    b
    字段,则可能不必重写
    hashCode()
    方法,但如果在子类的实现中考虑
    c
    ,则类作为键的工作可能会更好。也就是说,它会将具有不同
    c
    值的键放入不同的bucket中,而不是将具有相同
    a
    b
    的所有实例聚集在同一个hash bucket中。

    ++to Jordan Bently

    对于您编写的每个类,通常最好重写
    equals()
    toString()
    hashCode()
    。实际上,这并不总是有意义的。要不是你在做什么,我会这么做的。是的,您可以在子类中更改实现


    最好使用
    @Override
    标记每个被重写的方法,以帮助向要重写的开发人员提供文档。这提示他们,如果不是您的超类,您至少正在重写
    java.lang.Object

    这取决于您的超类。假设您的超类是
    A
    ,而
    B扩展了A
    ,那么这可能会发生

    • a.等于(a)
    • b.等于(b)
    • a.equals(b)
      (真)?b、 hash==a.hash:hash不重要
    • b.等于(a)
      (真)?b、 hash==a.hash:hash不重要
    A
    B
    应该如何关联?有两种选择:

  • A
    B
    是完全不同的,因此
    A.equals(B)
    B.equals(A)
    始终为false。这是最安全的方法。您需要在equals中测试
    a.getClass()==b.getClass()
    以确保
    a
    b
    完全相同的类型。例如,Eclipse IDE在generate equals()和hashCode()中默认自动生成此类等式
  • A
    B
    可以比较,但不能在
    B
    中覆盖它以保持
    equals()
    hashCode()的契约。
    这是由于equals的对称契约(
    A.equals(B)==B.equals(A)
    )而强制的

  • 为了确定hashCode和equals的行为,您需要
    class Foo { int a, b; }
    class Bar extends Foo { int c;}
    
    Foo x = new Foo(a,b);
    Bar y = new Bar(a,b,c);
    x.equals(y); //returns false
    y.equals(x); //returns true