java - 在继承层次结构中实现健壮的 equals() 和 hashCode() 方法的正确方法是什么?
问题描述
我有以下抽象Person
类:
import java.util.Objects;
public abstract class Person {
protected String name;
protected int id;
public Person(String name, int id) {
this.name = name;
this.id = id;
}
public abstract String description();
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(!(obj instanceof Person)) return false;
return Objects.equals(this.name, ((Person) obj).name) &&
this.id == ((Person) obj).id;
}
@Override
public int hashCode() {
return Objects.hash(this.name, this.id);
}
}
现在我有一个Person
名为的子类Employee
:
import java.time.LocalDate;
import java.util.Objects;
public class Employee extends Person {
private double salary;
private LocalDate hireDay;
public Employee(String name, int id, double salary, int year, int month, int day) {
super(name, id);
this.salary = salary;
this.hireDay = LocalDate.of(year, month, day);
}
@Override
public String description() {
return "Employee with a salary of " + this.salary;
}
@Override
public int hashCode() {
return super.hashCode() + Objects.hash(this.salary,this.hireDay);
}
@Override
public boolean equals(Object obj) {
return super.equals(obj) &&
Double.compare(this.salary, ((Employee) obj).salary) == 0
&& Objects.equals(this.hireDay,((Employee)obj).hireDay);
}
要正确实现 equals 方法,它必须符合以下约定。
自反:x.equals(x) 始终为真
对称:x.equals(y) 等价于 y.equals(x)
传递:x.equals(y) 和 y.equals(z) 蕴含 x.equals(z)是真的
当我在子类内部调用超类的equals()方法时,我首先确保所有被比较的对象都是超类的子类。这个问题解决了比较混合类型的问题,并照顾了上面提到的合同。我不再需要使用以下 equals 实现:
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
else if(obj == null || this.getClass() != obj.getClass()) return false;
Employee other = (Employee) obj;
return Objects.equals(this.name, other.name) &&
Double.compare(this.salary, other.salary) == 0 &&
Objects.equals(this.hireDay, other.hireDay);
}
也就是说,我不再需要显式检查当前对象 ( ) 是否与使用运算符的超类中的方法this
属于同一类。obj
instance of
将该实现放在超类的等于运算符中是否更健壮,或者使用该getClass()
方法在子类中使用更明确的测试以符合合同更好?
就 hashCode() 方法而言,我对特定于子类的私有实例字段进行哈希处理,然后简单地将其添加到超类中哈希方法的结果中。我找不到任何文档来说明这是否是在一般情况下或在继承层次结构中实现 hashCode() 函数的正确方法。我见过人们明确指定自己的哈希函数的代码。
如果我的问题过于笼统,我深表歉意,但我尽我所能地问他们,但不会太模棱两可。
编辑:
我要求 Intellij 实现一个 equals 和 hashcode 方法,它决定使用我上面发布的最后一个实现。那么,在什么情况下我会instance of
在超类中使用呢?当我在超类中实现最终的equals方法时会不会是这样,例如仅根据用户ID比较Person对象?
解决方案
两个人有没有可能永远一样id
?它不应该。所以逻辑延伸到Employee
类,这意味着在类中实现equals
和就足够了。hashCode
Person
此时,由于您只处理一个int
,您可以使用Integer.hashCode(id)
forhashCode
并仅比较 的值equals
。
推荐阅读
- javascript - 如何测试一系列交互?
- python - psycopg2.errors.SyntaxError:“<”处或附近的语法错误
- python - 从列表中的每个值中减去动态值
- php - 您将如何通过 PHP 创建由点组成的文本图像?
- utf-8 - Powerbuilder:在没有 bom 的情况下将 UTF-8 转换为 UTF-8
- c++ - I want to catch a generic exception as my Api can crash due to many reason. So I cannot throw for each and every step. below is the sample code
- python - python jupyter ipynb vscode
- azure-ad-b2c - 防止在静默令牌获取中执行编排步骤
- google-sheets - 在 Google 表格中逃跑
- node.js - npm 错误!安装 Shopify starter-theme-master 时的代码 ELIFECYCLE