欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

equals()方法和hashCode()方法是否需要同时重写

程序员文章站 2022-04-14 21:09:17
...

问题分析

在讨论这个问题之前,先给出结论:如果重写其中一个方法,则另外一个方法也必须重写.
我们都知道,如果一个类创建了两个实例,相比较这两个实例是否相等需要重写Object类的equals()方法。
那么equals方法是怎么执行的呢,下面来分析以下,首先拿大家都非常熟悉的String类型做说明
string重写的equals()方法源码:

    public boolean equals(Object anObject) {
    // 首先,判定两个待比较的数据的地址值是否一致,若一致返回true
        if (this == anObject) {
            return true;
        }
        //如果待比较的数据可以向下转型为String, 则挨个字符对比,全部一致返回true
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        //若无法向下转型,返回false
        return false;
    }

再看Objects的equals()方法怎么做的,这个方法非常经典,由于它容忍空指针,所以平常比较字符串的时候大家都很喜欢用

    public static boolean equals(Object a, Object b) {
    //非常简单,如果地址值一致则返回true,如果a自身的equals()方法判定与b相同也返回true
        return (a == b) || (a != null && a.equals(b));
    }

那么现在如果自定义一个类重写equals,重写的规则是什么呢?定义一个People类

package com.cmdc.review.javap;

import java.util.Objects;

/**
 * @author : wuwensheng
 * @date : 9:55 2020/6/30
 */
public class People {
    private String name;
    private int age;

    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;//如果两个对象的地址值相同 直接return true
        if (o == null || getClass() != o.getClass()) return false;//如果传递的对象类型和本类对象类型不一致 直接return false
        People people = (People) o;
        //具体开始比较people的各个属性,基本类型使用==,其余类型调用其自身重写的equals()方法
        return age == people.age &&
                Objects.equals(name, people.name);
    }

    @Override
    public int hashCode() {

        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

以上就是对equals()方法的说明,无论一个类有多少属性,equals()方法的套路都是一致的,先比较地址值,再向下转型挨个字段比较。
hashCode()方法说明
hashCode()是object类的方法,如果不重写hashCode()方法,那么就是在用父类Object的hashCode()方法,Object的hashCode()会用两个对象的地址值做hash运算(是不是地址值有争论,但是我觉得可以按照地址值)。若重写hashCode(),则根据对象的各个属性得出hash码值。
Object的源码

    public native int hashCode();

重写hashCode()将会执行的源码

    @Override
    public int hashCode() {
     // 重写之后调用Objects的hash()方法
        return Objects.hash(name, age);
    }

点进去调用Arrays的hashCode()方法

    public static int hash(Object... values) {
        return Arrays.hashCode(values);
    }

最后看Arrays的hashCode()方法怎么操作的

    public static int hashCode(Object a[]) {
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a)
            result = 31 * result + (element == null ? 0 : element.hashCode());

        return result;
    }

因此,hashCode重写之后是根据各个属性计算得出的哈希码值

结论

如果仅仅重写了equals而不重写hashCode,那么可能得出的结论是两个对象的
equals结果相同但hashCode不同,这是很荒唐的

示例代码:
equals()方法和hashCode()方法是否需要同时重写
所以,两个方法必须全部重写!

相关标签: java