关于Object中equals方法和hashCode方法判断的分析

作者:Haozz_1994 时间:2023-12-23 19:41:53 

首先提出这样一个问题:

如果两个对象不相同,他们的hashCode值一定不相等吗?

我们都知道equals和hashCode是Object中的方法,java中每一个对象都具有这两个方法。

  • equals(Object obj):判断两个对象是否“相同”,返回true或false;


public boolean equals(Object obj) {
   return (this == obj);
}
  • hashCode():将该对象的内部地址作为一个int值返回


public native int hashCode();

再来看两条关于这两个方法的规范:

  1. 如果重写equals(Object obj)方法,有必要重写hashCode()方法,以确保equals(Object obj)方法返回为true的两个对象有相等的hashCode()返回值。也就是说,如果两个对象相同,他们的hashCode值应该相等;

  2. 如果equals(Object obj)方法返回false,即两个对象不“相同”,并不要求这两个对象调用hashCode()方法有不相等的返回值。也就是说,如果两个对象不相同,他们的hashCode可能相等。

当然,上述只是规范。针对规范1,如果重写equals(Object obj)返回true,而hashCode()方法返回不相等的值,也是可以编译过的。

这样我们可以作出如下推论:

  1. 如果两个对象equals,理论上讲他们的hashCode一定相等(至少Java环境会这样认为);

  2. 如果两个对象不equals,他们的hashCode有可能相等;

  3. 如果两个对象hashCode相等,他们不一定equals;

  4. 如果两个对象hashCode不相等,他们一定不equals。

看着有点绕,其实原理很简单。我们从推论3和推论4可以预测:

Java在判断两个对象是否“相同”时,首先判断他们的hashCode()方法是否返回相等的int值,其次判断equals方法是否返回true。

我们可以写一段简单的代码测试一下:

首先写一个Java类:


public class Person {
 //重写equals方法,始终返回false;
 @Override
 public boolean equals(Object obj) {
   System.out.println("判断Person的equals");
   return false;
 }
 //重写hashCode方法,始终返回1;
 @Override
 public int hashCode() {
   System.out.println("判断Person的hashCode");
   return 1;
 }
}

上述代码中Person类重写了equals方法,打印并始终返回false,重写了hashCode方法,打印并始终返回1。

我们都知道Map中要求键不能重复,也就是不能“相同”,所以可以写如下的测试类:


public class TestPerson {
 @Test
 public void test(){
   Map<Person,Object> map = new HashMap<>();
   map.put(new Person(),new Object());//放入第1个Person-Object键值对;
   System.out.println("=====================");
   map.put(new Person(),new Object());//放入第2个Person-Object键值对;
   System.out.println(map.size());
 }
}

运行,打印结果如下

判断Person的hashCode
=====================
判断Person的hashCode
判断Person的equals
2

我们来分析一下:

  1. 当放入第1个Person-Object键值对时,Java会判断map中有没有和当前添加的new Person()相同的对象,于是去调用了Person的hashCode()方法,得到返回值1,发现此时map中没有相等的hashCode为1的Person对象(因为此时map为空),所以不再判断equals方法,将这个键值对放入map中;(推论4:如果两个对象hashCode不相等,他们一定不equals)

  2. 当放入第2个Person-Object键值对时,Java依然采用相同的判断方式,hashCode()方法判断之后得到返回值为1,发现此时map中有相等的hashCode值的Person对象,然后再去判断equals方法,得到返回值false(推论3:如果两个对象的hashCode相等,他们不一定equals),认为这两个对象不相同,于是将第2个键值对也放入map中。执行之后得到map的size为2

所以可以得出结论:

Java在判断两个对象是否“相同”时,首先判断他们的hashCode()方法是否返回相等的int值,如果不相等则直接认为他们不“相同”,如果相等,再判断equals方法是否返回true。

针对上述代码,可以在equals方法和hashCode方法中分别打断点,Debug运行,这样会看得比较清楚一点。

我们回到最初的那个问题:如果两个对象不相同,他们的hashCode值一定不相等吗?

上述代码中的场景就充分说明两个对象不相同时hashCode值却相等的场景,当然,这是不按照规范操作的情况。所以写代码时一定要按照规范要求的去做,避免不必要的BUG

可以试想一下,如果将上述代码中重写equals方法中的始终返回false改为始终返回true,又会是怎样的结果。

来源:https://blog.csdn.net/hz_940611/article/details/80365983

标签:java,object,equals,hashcode
0
投稿

猜你喜欢

  • spring mvc路径匹配原则详解

    2021-07-23 06:34:27
  • 基于Java实现一个简单的单词本Android App的实践

    2023-04-17 21:27:39
  • C语言结构体版学生成绩管理系统

    2021-11-05 03:29:41
  • C# Dockpanel入门基础必看篇

    2023-02-24 18:50:42
  • 分析Android Choreographer源码

    2022-09-04 07:25:12
  • 新手入门Jvm--jvm概览

    2023-11-09 15:42:31
  • Android:Field can be converted to a local varible.的解决办法

    2022-01-23 16:53:14
  • Android 破解视频App去除广告功能详解及解决办法总结

    2022-07-16 23:28:50
  • Java字符串拼接新方法 StringJoiner用法详解

    2022-06-16 13:02:13
  • C#窗体编程不显示最小化、最大化、关闭按钮的方法

    2023-03-03 00:04:29
  • 浅试仿 mapstruct实现微服务编排框架详解

    2022-07-12 13:20:44
  • ListView的View回收引起的checkbox状态改变监听等问题解决方案

    2023-07-26 17:33:45
  • 超简单C#获取带汉字的字符串真实长度(单个英文长度为1,单个中文长度为2)

    2021-11-13 20:37:55
  • 详解关于SpringBoot的外部化配置使用记录

    2023-08-10 03:54:54
  • Java动态规划之硬币找零问题实现代码

    2023-01-23 20:37:38
  • Java中一些关键字的使用技巧总结

    2023-11-19 02:48:49
  • spring-boot-maven-plugin 配置有啥用

    2022-08-27 19:09:25
  • C#文件和字节流的转换方法

    2022-03-18 05:39:43
  • Kotlin与java8的SAM转换对比(进阶)

    2023-05-15 11:50:35
  • C#通过WIN32 API实现嵌入程序窗体

    2021-08-13 04:53:10
  • asp之家 软件编程 m.aspxhome.com