说一下你真的了解 equals 方法吗?

equals() & hashCode()

i. 首先,简单介绍一下具体用法


  • boolean equals(Object obj) – 用于判断调用对象是否与参数对象相等
    – $\color{red}该方法默认比较两个对象的地址,与 “==” 等效$
    – 若希望比较对象的内容,则需要进行方法的重写
    – 若该方法重写了,则应该去重写hashCode()方法,以维护 hashCode 方法的常规协定
  • int hashCode() – 用于获取调用对象的哈希码值(内存地址和编号)并返回
    – 若两个对象调用equals()方法相等,则各自调用该方法得到的哈希码值必须相同
    – 若两个对象调用equals()方法不相等,则各自调用该方法的结果可以相同,但是最好不相同

ii. 一个案例带你搞懂 equals() 和 hashCode()

  • 首先,我们创建一个Student类// Student类封装
    public class Student {

    private int id;
    private String name;

    public Student() {
    super();
    }

    public Student(int id, String name) {
    super();
    this.id = id;
    this.name = name;
    }

    public int getId() {
    return id;
    }
    public void setId(int id) {
    if (id > 0) {
    this.id = id;
    } else {
    System.out.println(“学号不合理!”);
    }
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public class TestStudent {

    public static void main(String[] args) {

    Student s1 = new Student(1001, “老王”);
    Student s2 = new Student(1001, “老王”);

    System.out.println(s1 + ” ” + s2);
    // 调用equals方法来判断两个对象是否相同,这里默认从Object类中继承

    boolean b1 = s1.equals(s2);
    System.out.println(“b1 = “+b1); // b1 = false
    System.out.println(s1 == s2); // false
    }

    }Euqals.Student@2f92e0f4 Euqals.Student@28a418fc
    b1 = false
    false// Student类封装
    public class Student {

    private int id;
    private String name;

    public Student() {
    super();
    }

    public Student(int id, String name) {
    super();
    this.id = id;
    this.name = name;
    }

    public int getId() {
    return id;
    }
    public void setId(int id) {
    if (id > 0) {
    this.id = id;
    } else {
    System.out.println(“学号不合理!”);
    }
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
    // 1. 若两个对象的地址一样,则内容一定相同
    if (this == obj) {
    return true;
    }
    // 2. 若调用对象不为空, 参数对象为空,则内容一定不相同 (如t1.equals(null))
    else if (obj == null) {
    return false;
    }
    // 3. 若参数对象和调用对象类型一致,则由学号来决定两个对象内容是否相同
    else if (obj instanceof Student) {

    Student s = (Student)obj;
    if (this.getId() == s.getId()) {
    return true;
    } else {
    return false;
    }
    }
    // 4. 若参数对象和调用对象类型不一致,则内容一定不相同
    else {
    return false;
    }
    }System.out.println(“你好”.equals(“你好”)); // truetrue

  • 在TestStudent类中进行测试
  • 显然,因为equals方法默认比较的是地址,这里s1与s2地址不同,输出为false。那么,如果我们想要另两个对象学号相同时,使用equals 方法时输出为true 应该怎么做呢,很显然,equals方法是属于Object类的,那么我们只要在Student类中对其进行重写即可
  • 这里,我们对4中情况进行了考虑,我们再次运行TestStudent代码,发现此时输入了true,因为当我们重写equals方法后,则调用子类重写以后的版本,比较内容。
  • 在这里,我们会想到String类,那么我们对String对象调用equals方法会输出什么呢?
  • 这里输出的是true,我们知道这是两个String对象,输出不应该是false吗?根据前面所讲的,我们明白了,原来 $\color{red}String类中也对equals方法进行了重写$, 那么我们就明白了。到这里就完了吗?不,还没有,前面我们说过,一般为了维护hashCode方法的常规协定,我们要在Student类中重写 hashCode方法 // 为了保证和equals方法结果一致性,需要重写hashCode
    @Override
    public int hashCode() {

    // return getId();

    // 随便定义,为了保持ID相同
    // 维护hashCode方法的常规协定
    int type = 12;
    return type*31 + getId();
    }

  • 我们在TestStudent类中进行测试 // 调用从Object类中继承的hashCode方法来获取对应的哈希码
    // 当Student类中重写hashCode方法后,则调用重写以后的版本
    int res = s1.hashCode();
    System.out.println(“res = ” + res);

    res = s2.hashCode();
    System.out.println(“res = ” + res);res = 1373
    res = 1373

  • 这里就达到了我们想要的结果,你Get到了吗?

喜欢就关注博主吧,你的关注点赞是对博主最大的鼓励!:smile:

正文完