equals() 和 hashCode()
本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 42 课,共 87 课。
在 Java 中比较对象时,== 运算符会检查两个引用是否指向同一个内存位置。要比较对象的实际内容,你需要重写 equals() 方法。
public class Person {
private String name;
private int age;
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && name.equals(person.name);
}
}equals() 方法遵循一个标准模式:先检查是否是同一个对象,然后验证类型,最后比较相关字段。
每当你重写 equals() 时,也必须重写 hashCode()。这是 Java 中的一项约定:相等的对象必须具有相同的哈希码。基于哈希的集合(如 HashMap 和 HashSet)依赖这条规则才能正常运行。
@Override
public int hashCode() {
return Objects.hash(name, age);
}Objects.hash() 工具方法会根据与 equals() 相同的字段生成哈希码。如果两个 Person 对象的姓名和年龄相同,它们就会被视为相等,并生成相同的哈希码,从而确保它们在集合中的行为一致。
挑战
简单让我们构建一个能正确实现对象相等性判断的学生记录系统。你将创建一个 Student 类,当两个学生的学生 ID 和姓名相同时,就认为他们相等,无论他们在内存中是否是同一个对象。
你需要将代码分成两个文件:
Student.java:创建一个表示学生的类,包含三个私有字段:studentId(String)、name(String)和gpa(double)。添加一个用于初始化所有字段的构造函数,以及每个字段对应的 getter 方法。重写
equals()方法,使两个 Student 对象在studentId相同且name相同时被视为相等。遵循标准模式:检查是否为同一个引用,检查是否为 null 以及类型是否相同,然后比较相关字段。使用
Objects.hash()重写hashCode()方法,并使用与equals()中相同的字段。记得在文件顶部导入java.util.Objects。Main.java:通过比较学生对象,让你的 Student 类发挥作用。你会收到 6 个输入,分别表示两名学生的信息:第一名学生的 ID、姓名和 GPA,然后是第二名学生的 ID、姓名和 GPA。创建两个 Student 对象,然后进行三次比较并打印结果:
- 打印
Same reference:,后面接第一名学生是否等于自身(结果应始终为 true) - 打印
Content equality:,后面接第一名学生是否等于第二名学生(根据你的 equals 实现判断) - 打印
Hash codes match:,后面接两名学生的哈希码是否相同
- 打印
你会收到 6 个输入:第一名学生的 ID(String)、第一名学生的姓名(String)、第一名学生的 GPA(double)、第二名学生的 ID(String)、第二名学生的姓名(String),以及第二名学生的 GPA(double)。
注意,当两名学生的 ID 和姓名相同时,equals() 会返回 true,而且他们的哈希码也相同。这就是你必须遵守的约定!
亲手试试
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取第一个学生的数据
String id1 = scanner.nextLine();
String name1 = scanner.nextLine();
double gpa1 = scanner.nextDouble();
scanner.nextLine(); // 读取并丢弃换行符
// 读取第二个学生的数据
String id2 = scanner.nextLine();
String name2 = scanner.nextLine();
double gpa2 = scanner.nextDouble();
// TODO: 使用输入数据创建两个 Student 对象
// TODO: 输出 "Same reference: ",然后输出 student1 是否等于自身
// TODO: 输出 "Content equality: ",然后输出 student1 是否等于 student2
// TODO: 输出 "Hash codes match: ",然后输出两个学生的哈希码是否相同
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
7特殊方法与 Object 类
toString() 方法equals() 和 hashCode()clone() 方法compareTo() 和 ComparableComparator 接口回顾:自定义排序自己练习: Java 在线编译器