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

问题分析

在讨论这个问题之前,先给出结论:如果重写其中一个方法,则另外一个方法也必须重写.
我们都知道,如果一个类创建了两个实例,相比较这两个实例是否相等需要重写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不同,这是很荒唐的

示例代码:
在这里插入图片描述
所以,两个方法必须全部重写!

展开阅读全文
©️2020 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值