JAVA语言-Object类的equals方法和hashCode方法
周鸣君 2018-04-04 来源 : 阅读 1630 评论 0

摘要:文主要介绍了JAVA语言的Object 类,它是所有类的父类,Object类中定义了很多重要的方法,有些基础方法是必须要搞清楚的,今天我们就来学习下Object类中的equals方法和hashCode方法。让我们在JAVA语言中走的更远。

Object 类是所有类的父类,Object类中定义了很多重要的方法,有些基础方法是必须要搞清楚的,今天我们就来学习下Object类中的equals方法和hashCode方法。

 

一、equals方法

首先我们来看下Object类的equals方法的源码:

Java代码  

1. public boolean equals(Object obj) {  
2.         return (this == obj);  
3. }

很明显它是比较两个对象的引用(即内存地址)是否相等。如果你不知道这个,想当然的以为它比较的是内容,比如我们要比较两个用户对象是否相等:

User实体类:

Java代码  

1. public class User {  
2.       
3.     private int userId;  
4.     private String userName;  
5.     private int age;  
6.       
7.     public User(int userId, String userName, int age) {  
8.         this.userId = userId;  
9.         this.userName = userName;  
10.         this.age = age;  
11.     }  
12.       
13.     public int getUserId() {  
14.         return userId;  
15.     }  
16.     public void setUserId(int userId) {  
17.         this.userId = userId;  
18.     }  
19.     public String getUserName() {  
20.         return userName;  
21.     }  
22.     public void setUserName(String userName) {  
23.         this.userName = userName;  
24.     }  
25.     public int getAge() {  
26.         return age;  
27.     }  
28.     public void setAge(int age) {  
29.         this.age = age;  
30.     }  
31. }

测试代码: 

Java代码  

1. public class UserTest {  
2.       
3.     public static void main(String[] args) {  
4.         User u1 = new User(1, "z3", 25);  
5.         User u2 = new User(1, "z3", 25);  
6.         boolean b = u1.equals(u2);  
7.         System.out.println(b);  
8.     }  
9.   
10. }

执行结果为:false,为什么呢,因为你调用的是Object类的equals方法,它比较的是两个对象的引用,即内存地址,在Java虚拟机的堆上是两块独立的内存空间,绝对不相等的。并不是我们想要的结果,那应该要怎么做呢?自己重写Object类的equals方法就好了:

我们在User实体类中添加equals方法:

Java代码  

1.       @Override  
2. ublic boolean equals(Object obj) {  
3. if (obj == null)  
4.     return false;  
5. if(obj instanceof User) {  
6.     User other = (User) obj;  
7.     if (age != other.age)  
8.         return false;  
9.     if (userId != other.userId)  
10.         return false;  
11.     if (userName == null) {  
12.         if (other.userName != null)  
13.             return false;  
14.     } else if (!userName.equals(other.userName))  
15.         return false;  
16. }  
17. return true;

再次执行测试代码,结果为:true

我们可以看到重写的equals方法,比较了User类的每一个成员变量,那成员变量之间怎么比较呢,如果是基本数据类型如int,float,double,boolean等,直接比较其值就行了。

如果是字符串,直接调用字符串的equals方法即可,因为String类帮我们重写了equals方法,我们来看它的源码:

Java代码  

1. public boolean equals(Object anObject) {  
2.         if (this == anObject) {  
3.             return true;  
4.         }  
5.         if (anObject instanceof String) {  
6.             String anotherString = (String)anObject;  
7.             int n = value.length;  
8.             if (n == anotherString.value.length) {  
9.                 char v1[] = value;  
10.                 char v2[] = anotherString.value;  
11.                 int i = 0;  
12.                 while (n-- != 0) {  
13.                     if (v1[i] != v2[i])  
14.                         return false;  
15.                     i++;  
16.                 }  
17.                 return true;  
18.             }  
19.         }  
20.         return false;  
21.     }

 可以看出String类的eqauls方法比较的是每一个char字符。其实查看Jdk源码,可以发现,各基本数据类型的包装类如Integer,Float,Double,Boolean等都重写了Object类的equals方法。因为实际业务需要我们去比较对象或变量的内容而不是引用。

 

二、hashCode方法

Object类的hashCode方法源码如下:

Java代码  

1. public native int hashCode();

它是一个本地方法,返回一个int类型的整数。 

Java为每一个对象提供一个int类型的hashCode,其目的是快速查找定位对象,猜测啊,在底层有一张Hash表,存储对象的hashCode和内存地址的映射,这样方便JVM在内存中能够快速查找定位到某个对象,不然,内存中那么多的对象,JVM如何查找一个对象呢。

 

hashCode有几个重要特性:

1.hashCode是为了查找对象或元素提高性能

2.如果两个对象equals相等,那么两个对象的hashCode一定相等

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

4.如果要重写对象的equals方法,尽量要重写对象的hashCode方法

 

接下来,我们一一说明:

第1点,hashCode是为了查找对象或元素提高性能,这在上面已经说了JVM要查找内存中的对象可以快速定位。还有就是集合类的实现,比如Set集合,元素不允许重复,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。于是采用Java的哈希表原理,先根据元素的hashCode定位元素位置,如果该位置元素不存在,则将元素插入集合的该位置,如果已经存在,则equals比较其内容,如果内容一致则元素重复了,否则采用链式数据结构存储到该位置(HashMap的实现)。

 

第2点,如果两个对象equals相等,那么两个对象的hashCode一定相等。这个上面的Set集合就已经解释了,如果两个对象equals相等,hashCode不相等,那么根据Set集合实现会将两个元素存储到不同的位置,那么这就违背Set集合元素不允许重复了。

 

第3点,如果两个对象的hashCode相等,两个对象的equals不一定相等。这个我们看下Set的实现HashSet,其底层是HashMap的实现:

Java代码  

1. public V put(K key, V value) {  
2.     if (key == null)  
3.         return putForNullKey(value);  
4.     int hash = hash(key.hashCode());  
5.     int i = indexFor(hash, table.length);  
6.     for (Entry<K,V> e = table[i]; e != null; e = e.next) {  
7.        Object k;  
8.         if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  
9.             V oldValue = e.value;  
10.             e.value = value;  
11.             e.recordAccess(this);  
12.             return oldValue;  
13.         }  
14.     }  
15.   
16.     modCount++;  
17.     addEntry(hash, key, value, i);  
18.     return null;  
19. }

根据HashMap的put方法实现,我们可以看到首先根据key的hashCode计算出元素在哈希表的位置,如果该位置上已经有元素(说明这两元素的hashCode相等),再equals比较两元素的内容,如果不相等,则以链表的方式将两元素存储在该位置,这充分说明了两元素hashCode相等,但equals不一定相等。

 

第4点,如果要重写对象的equals方法,尽量要重写对象的hashCode方法,这个其实就是保证第2点的实现,如果不重写hashCode方法,还是以Set集合为例,就无法保证元素不重复。可以查看jdk源码,像String类,Integer类等只要重写了equals方法的,都重写了hashCode方法。

 

 

总结,我们在开发中,养成良好的习惯,每写一个实体类,就重写它的equals方法和hashCode方法,要么都不写,要写两个都要写,可以减少不必要的问题发生。

 本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言JAVA频道!


本文由 @职坐标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论
本文作者 联系TA

擅长Hadoop/Spark大数据技术

  • 10
    文章
  • 5531
    人气
  • 87%
    受欢迎度

已有15人表明态度,87%喜欢该老师!

进入TA的空间
求职秘籍 直通车
  • 索取资料 索取资料 索取资料
  • 答疑解惑 答疑解惑 答疑解惑
  • 技术交流 技术交流 技术交流
  • 职业测评 职业测评 职业测评
  • 面试技巧 面试技巧 面试技巧
  • 高薪秘笈 高薪秘笈 高薪秘笈
TA的其他文章 更多>>
JAVA语言-java中的字符串
经验技巧 100% 的用户喜欢
JAVA语言——网络编程、反射
经验技巧 0% 的用户喜欢
JAVA从入门到精通-java中array的常用操作
经验技巧 0% 的用户喜欢
JAVA语言-Java中jstat的用法
经验技巧 0% 的用户喜欢
JAVA语言-java中lambda表达式的使用
经验技巧 0% 的用户喜欢
其他海同师资 更多>>
吕益平
吕益平 联系TA
熟悉企业软件开发的产品设计及开发
孔庆琦
孔庆琦 联系TA
对MVC模式和三层架构有深入的研究
范佺菁
范佺菁 联系TA
擅长Java语言,只有合理的安排和管理时间你才能做得更多,行得更远!
金延鑫
金延鑫 联系TA
擅长与学生或家长及时有效沟通
程光淼
程光淼 联系TA
精通C、C++等语言、智能芯片开发
经验技巧30天热搜词 更多>>

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程