wj.*_*wj. 62 java inheritance overriding equals hashcode
是否有关于如何重写特定规则equals()与hashCode()在子类考虑超领域?知道有很多参数:超级字段是私有/公共的,有/无getter ...
例如,Netbeans生成的equals()&hashCode()将不考虑超级字段...和
new HomoSapiens("M", "80", "1.80", "Cammeron", "VeryHot").equals(
new HomoSapiens("F", "50", "1.50", "Cammeron", "VeryHot"))
Run Code Online (Sandbox Code Playgroud)
将返回true :(
public class Hominidae {
public String gender;
public String weight;
public String height;
public Hominidae(String gender, String weight, String height) {
this.gender = gender;
this.weight = weight;
this.height = height;
}
...
}
public class HomoSapiens extends Hominidae {
public String name;
public String faceBookNickname;
public HomoSapiens(String gender, String weight, String height,
String name, String facebookId) {
super(gender, weight, height);
this.name = name;
this.faceBookNickname = facebookId;
}
...
}
Run Code Online (Sandbox Code Playgroud)
如果你想看到Netbeans生成的equals()和hashCode():
public class Hominidae {
...
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Hominidae other = (Hominidae) obj;
if ((this.gender == null) ? (other.gender != null) : !this.gender.equals(other.gender)) {
return false;
}
if ((this.weight == null) ? (other.weight != null) : !this.weight.equals(other.weight)) {
return false;
}
if ((this.height == null) ? (other.height != null) : !this.height.equals(other.height)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 5;
hash = 37 * hash + (this.gender != null ? this.gender.hashCode() : 0);
hash = 37 * hash + (this.weight != null ? this.weight.hashCode() : 0);
hash = 37 * hash + (this.height != null ? this.height.hashCode() : 0);
return hash;
}
}
public class HomoSapiens extends Hominidae {
...
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final HomoSapiens other = (HomoSapiens) obj;
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
return false;
}
if ((this.faceBookNickname == null) ? (other.faceBookNickname != null) : !this.faceBookNickname.equals(other.faceBookNickname)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 7;
hash = 89 * hash + (this.name != null ? this.name.hashCode() : 0);
hash = 89 * hash + (this.faceBookNickname != null ? this.faceBookNickname.hashCode() : 0);
return hash;
}
}
Run Code Online (Sandbox Code Playgroud)
CPe*_*ins 56
儿童不应该检查父母的私人成员
但很明显,所有重要的领域都应该考虑到平等和散列.
幸运的是,您可以轻松满足这两个规则.
假设您没有使用NetBeans生成的equals和hashcode,您可以修改Hominidae的equals方法以使用instanceof比较而不是类相等,然后直接使用它.像这样的东西:
@Override
public boolean equals(Object obj) {
if (obj == null) { return false; }
if (getClass() != obj.getClass()) { return false; }
if (! super.equals(obj)) return false;
else {
// compare subclass fields
}
Run Code Online (Sandbox Code Playgroud)
当然,哈希码很简单:
@Override
public int hashCode() {
int hash = super.hashCode();
hash = 89 * hash + (this.name != null ? this.name.hashCode() : 0);
hash = 89 * hash + (this.faceBookNickname != null ? this.faceBookNickname.hashCode() : 0);
return hash;
}
Run Code Online (Sandbox Code Playgroud)
但是,严肃地说:NetBeans没有通过调用超类方法来考虑超类字段?
mat*_*t b 20
我更喜欢使用commons-lang包中的EqualsBuilder(和HashcodeBuilder)来使我的equals()和hashcode()方法更容易阅读.
例:
public boolean equals(Object obj) {
if (obj == null) { return false; }
if (obj == this) { return true; }
if (obj.getClass() != getClass()) {
return false;
}
MyClass rhs = (MyClass) obj;
return new EqualsBuilder()
.appendSuper(super.equals(obj))
.append(field1, rhs.field1)
.append(field2, rhs.field2)
.append(field3, rhs.field3)
.isEquals();
}
Run Code Online (Sandbox Code Playgroud)
一般来说,跨子类实现equals很难保持对称和传递.
考虑到检查现场的超x和y,和子检查x,y和z.
所以Subclass == Superclass == Subclass,其中z在Subclass的第一个实例和第二个实例之间是不同的,违反了契约的传递部分.
这就是为什么equals的典型实现将检查getClass() != obj.getClass()而不是执行instanceof.在上面的示例中,如果SubClass或Superclass执行instanceof检查,它将破坏对称性.
所以结果是子类当然可以考虑super.equals(),但也应该进行自己的getClass()检查以避免上述问题,然后另外检查自己字段上的equals.它将是一个类的奇怪的鸭子,它根据超类的特定字段改变了自己的等于行为,而不仅仅是超类返回等于.
规则是:
因此,请使用完成规则所需的字段.