问题

为什么在重写equals()方法的同时,必须重写hashCode()方法?

解答

在《每天一道Java题[2]》中,已经对hashCode()能否判断两个对象是否相等做出了解释。equals()方法与hashCode()方法的关系如下:

  1. 如果两个对象的hashCode()返回值不一样,则equals()返回的结果必为false。
  2. 如果两个对象的hashCode()返回值一样的时候,equals()返回的结果未知。
  3. 如果两个对象的equals()返回的结果为true,则两个对象的hashCode()返回值必定相等。
  4. 如果两个对象的equals()返回的结果为false,则两个对象的hashCode()返回值可能不同也可能相同。

可以看出,equals()与hashCode()有着千丝万缕的关系。简单的说,如果只重写了equals(),没有重写hashCode()的话,因为hashCode()主要用于散列的集合,这就会造成,当使用equals()为true的两个相当的对象作为散列集合中的key时,会得出不一样的结果,这其中原因就是他们的hashCode()返回值不同。

看下面一个例子:

package me.huangzijian;

import java.util.HashMap;

public class EqualsAndHashCode {

    private String name;
private int num;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public EqualsAndHashCode(String name, int num){
this.name = name;
this.num = num;
}
@Override
public boolean equals(Object obj) {
if(this.name.equals(((EqualsAndHashCode)obj).getName())&&this.num==((EqualsAndHashCode)obj).getNum()){
return true;
}
else{
return false;
}
}
public static void main(String[] args) {
EqualsAndHashCode equalsAndHashCode1 = new EqualsAndHashCode("a", 1);
System.out.println("equalsAndHashCode1's hashCode is: " + equalsAndHashCode1.hashCode());
HashMap<EqualsAndHashCode, Integer> hashMap = new HashMap<EqualsAndHashCode, Integer>();
hashMap.put(equalsAndHashCode1, 1);
EqualsAndHashCode equalsAndHashCode2 = new EqualsAndHashCode("a", 1);
System.out.println("equalsAndHashCode2's hashCode is: " + equalsAndHashCode2.hashCode());
System.out.println("equalsAndHashCode1.equals(equalsAndHashCode2) is: " + equalsAndHashCode1.equals(equalsAndHashCode2));
System.out.println(hashMap.get(equalsAndHashCode2));
}
}

输出的结果:

equalsAndHashCode1's hashCode is: 1712811212
equalsAndHashCode2's hashCode is: 1508661727
equalsAndHashCode1.equals(equalsAndHashCode2) is: true
null

从中可以看到,equalsAndHashCode1与equalsAndHashCode2的equals()为true,但hashCode()返回值不一样,这就违背了一开始描述的equals()与hashCode()的关系了。而且也可以看出,在HashMap中,也获取不出相同key值(equalsAndHashCode1与equalsAndHashCode2的equals()值为true,则认为是相同的对象)的value值了。

引用

对于hashCode()与equals()之间的关系,也可以参考《Effective Java》一书中的描述:

  • 在程序执行期间,只要equals方法的比较操作用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法必须始终如一地返回同一个整数。
  • 如果两个对象根据equals方法比较是相等的,那么调用两个对象的hashCode方法必须返回相同的整数结果。
  • 如果两个对象根据equals方法比较是不等的,则hashCode方法不一定得返回不同的整数。

每天一道Java题[3]的更多相关文章

  1. 每天一道Java题[11]

    题目 synchronized怎么实现线程同步?请修改<每天一道Java题[10]>中的MyRunnableThread类以解决三个线程都获取到10的问题. 解答 方法一: 采用synch ...

  2. 每天一道Java题[4]

    问题 怎么将字符串转换为int? 解答 此题看似简单,但经常出现在笔试等地方,由于大家习惯了用IDE,有什么还真未必能写出来.通常都是parseInt()方法进行转换,如下: Int n = Inte ...

  3. 每天一道Java题[6]

    题目 String字符串怎么转换为Date,Date又怎么转换成String字符串 解答 String->Date 主要用到类SimpleDateFormat及其抽象父类DateFormat中的 ...

  4. 每天一道Java题[9]

    题目 native关键字的作用是什么? 解答 首先,需了解JNI(Java Native Interface),它是连接Java平台与本地C代码的一个API. 其次,用native关键字声明的方法,是 ...

  5. 每天一道Java题[1]

    问题:char[]与String相比,有什么优胜的地方? 回答: 针对安全保密高的信息,char[]比String做得更好.因为String是不可变得,即使你修改原先的变量,实际上也是在内存中新建一个 ...

  6. 每天一道Java题[2]

    问题 可以直接根据hashCode()方法产生的值判断两个对象是否相等吗? 解答 不能!根据Wikipedia(https://en.wikipedia.org/wiki/Java_hashCode( ...

  7. 每天一道Java题[5]

    题目 String.StringBuilder.StringBuffer有什么异同? 解答 相同点:String.StringBuilder.StringBuffer都可以用来存储字符串. 不同点: ...

  8. 每天一道Java题[7]

    题目 什么是REST原则,请解释RESTful架构,以及其设计思想? 解答 REST,全称为Representation State Transfer,是一种互联网软件的架构原则.凡是满足REST原则 ...

  9. 每天一道Java题[10]

    题目 阐述创建线程最常用的两种方法及其对比. 解答 方法一:继承Thread类实现 步骤: 创建Thread类的子类,如MyThread. 重写Thread类的run()方法. 实例化MyThread ...

随机推荐

  1. java的特点跨平台原理以及JDK的安装

    终于开始了期待已久的java,了解java首先要了解下计算机语言的发展历史 机器语言--->汇编语言--->--->高级语言(面向过程的语言和面向对象的语言) 机器语言 每一个计算机 ...

  2. Redis简单几步

    第一步redis安装:1.首先确认下载包为64位的还是32位的2.下载http://code.google.com/p/servicestack/downloads3.解压下载包得到以下文件:cygw ...

  3. C++ 网络爬虫实现

    最近有个概念吵得很火,网络爬虫,但是基本都是用什么python或者JAVA写,貌似很少看到用c++写的,我在网上找了一个,看到其实还是很简单的算法 算法讲解:1.遍历资源网站 2.获取html信息   ...

  4. String 类的实现(1)浅拷贝存在的问题

    浅拷贝 : 也称位拷贝 , 编译器只是直接将指针的值拷贝过来, 结果多个对象共用 同 一块内 存, 当一个对象将这块内 存释放掉之后, 另 一些对象不知道该块空间 已经还给了 系 统, 以 为还有效, ...

  5. Cobbler自动化部署最佳实践

    第1章 Cobbler自动化部署最佳实践 运维自动化在生产环境中占据着举足轻重的地位,尤其是面对几百台,几千台甚至几万台的服务器时,仅仅是安装操作系统,如果不通过自动化来完成,根本是不可想象的. 面对 ...

  6. Object-C开发常用宏定义

    Object-C开发中宏会将经常用到的系统常量进行封装,方便使用: 1.获取通知中心 #define EYNotificationCenter(name, object, userInfo) [[NS ...

  7. 【CreateJS】WebStorm+Adobe Animate CC 搭配开发HTML5,入门教程

    目的:动画设计师用Adobe Animate CC做好动画素材,发布好之后,交给程序员写交互代码:在WebStorm之类的ide里操纵 Animate 里面的变量,class等. 前提环境: ①安装好 ...

  8. 老李教你性能测试监控工具nmon

    老李教你性能测试监控工具nmon   loadrunner的某些性能监控器不够强大,这就需要我们利用更好的工具进行监控,在项目中我们会用nmon工具作为辅助性能监控的工具,帮助我们进行性能分析,pop ...

  9. 性能调优之Java系统级性能监控及优化

    性能调优之Java系统级性能监控及优化   对于性能调优而言,通常我们需要经过以下三个步骤:1,性能监控:2,性能剖析:3,性能调优 性能调优:通过分析影响Application性能问题根源,进行优化 ...

  10. 提交到SVN中的项目被删除 且项目名已经被新建项目占用找回方法

    提到项目找回,一看就头疼,找回起来较麻烦.下面就讲一下. 首先,确定项目是否被删除?找项目,太多了,都被找一遍了,还是没找到,看看就头痛,换了个方法,找了个项目的包,xx.apk,反编译下吧,过程略, ...