equals
首先,在计算orhashCode
方法时,不应包含来自超类的任何状态。该状态超出了您正在处理的类的范围,您的类应该依赖于超类而不是重写它的功能。
使用 IntelliJ生成equals
和hashCode
使用时,如果您想包含来自父类的任何计算,只需对添加调用super.equals(o)
or的方法进行小的修改super.hashCode()
。
实现这些方法的另一种方法是使用 Apache Commons Lang 库中的and ,EqualsBuilder
这些构建器提供语义来添加超级调用。HashCodeBuilder
编辑:
回答“此类实例上的相等性意味着什么将忽略子类的身份?” :正如您已经指出的那样,这意味着如果您有两个类,一个扩展另一个类,并且子类既不覆盖equals
或也不覆盖hashCode
,那么,在检查两个实例是否相等(或添加到散列结构)时,两者都会表现得好像他们来自同一个班级。这是一个例子:
class A {
private int intField = 2;
public A(int value) {
intField = value;
}
public boolean equals(Object o) {
if (null == o) return false;
if (this == o) return true;
if (!(o instanceof A)) return false;
return intField == ((A) o).intField;
}
public int hashCode() {
return 11 * intField;
}
}
class B extends A {
private boolean boolField = true;
public B(int intValue, boolean boolValue) {
super(intValue);
boolField = boolValue;
}
// no equals or hashCode
}
因此,使用这些课程,您将面临以下问题:
A a = new A(12);
B b = new B(12, false);
b.equals(a); // returns true
为避免这种情况,只需在 IntelliJ 中生成它们后在内部equals
或方法中添加一个超级调用。hashCode
class B extends A {
private boolean boolField = true;
public B(int intValue, boolean boolValue) {
super(intValue);
boolField = boolValue;
}
public boolean equals(Object o) {
if (null == o) return false;
if (this == o) return true;
if (!(o instanceof B)) return false;
if (!super.equals(o)) return false;
return boolField == ((B) o).boolField;
}
public int hashCode() {
int hash = super.hashCode();
hash += 11 * Boolean.valueOf(boolField).hashCode();
return hash;
}
}
正如我已经说过的,其他方式是使用 Apache Commons Lang 库中的构建器。