每天一道Java题[3]
问题
为什么在重写equals()方法的同时,必须重写hashCode()方法?
解答
在《每天一道Java题[2]》中,已经对hashCode()能否判断两个对象是否相等做出了解释。equals()方法与hashCode()方法的关系如下:
- 如果两个对象的hashCode()返回值不一样,则equals()返回的结果必为false。
- 如果两个对象的hashCode()返回值一样的时候,equals()返回的结果未知。
- 如果两个对象的equals()返回的结果为true,则两个对象的hashCode()返回值必定相等。
- 如果两个对象的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]的更多相关文章
- 每天一道Java题[11]
题目 synchronized怎么实现线程同步?请修改<每天一道Java题[10]>中的MyRunnableThread类以解决三个线程都获取到10的问题. 解答 方法一: 采用synch ...
- 每天一道Java题[4]
问题 怎么将字符串转换为int? 解答 此题看似简单,但经常出现在笔试等地方,由于大家习惯了用IDE,有什么还真未必能写出来.通常都是parseInt()方法进行转换,如下: Int n = Inte ...
- 每天一道Java题[6]
题目 String字符串怎么转换为Date,Date又怎么转换成String字符串 解答 String->Date 主要用到类SimpleDateFormat及其抽象父类DateFormat中的 ...
- 每天一道Java题[9]
题目 native关键字的作用是什么? 解答 首先,需了解JNI(Java Native Interface),它是连接Java平台与本地C代码的一个API. 其次,用native关键字声明的方法,是 ...
- 每天一道Java题[1]
问题:char[]与String相比,有什么优胜的地方? 回答: 针对安全保密高的信息,char[]比String做得更好.因为String是不可变得,即使你修改原先的变量,实际上也是在内存中新建一个 ...
- 每天一道Java题[2]
问题 可以直接根据hashCode()方法产生的值判断两个对象是否相等吗? 解答 不能!根据Wikipedia(https://en.wikipedia.org/wiki/Java_hashCode( ...
- 每天一道Java题[5]
题目 String.StringBuilder.StringBuffer有什么异同? 解答 相同点:String.StringBuilder.StringBuffer都可以用来存储字符串. 不同点: ...
- 每天一道Java题[7]
题目 什么是REST原则,请解释RESTful架构,以及其设计思想? 解答 REST,全称为Representation State Transfer,是一种互联网软件的架构原则.凡是满足REST原则 ...
- 每天一道Java题[10]
题目 阐述创建线程最常用的两种方法及其对比. 解答 方法一:继承Thread类实现 步骤: 创建Thread类的子类,如MyThread. 重写Thread类的run()方法. 实例化MyThread ...
随机推荐
- 原生JS实现弹出窗口的拖拽
上一篇说了一下弹出窗口功能的实现思路,一般情况下紧接着就会需要做到弹窗的移动,当然现在有很插件.库比如hammer可以使用,效率也非常好.但我觉得还是有必要了解一下原生JS的实现思路及方式,如下: 思 ...
- 【转】AS3多种天气预报调用代码分享
今天我们来介绍利用weather.com.cn上的天气预报功能,这里介绍了大家常用的,其它的大家可以自己去下载. 我们这里的天气预览不需要js来调用,只要用iframe就可以了,更不需要ASP/' t ...
- POPTEST老李分享session,cookie的安全性以及区别 3
如何查看服务器端输送到我们电脑中的这些Cookie信息: 点开IE浏览器或其他浏览器,在菜单栏中有工具选项,点开有InterNet选项: Cookie名称.来源.文件格式( ...
- 老李分享:Eclipse中开发性能测试loadrunner脚本
老李分享:Eclipse中开发性能测试loadrunner脚本 前篇我分享了如何用loadrunner搭建javauser的性能测试脚本环境,本次我来告诉大家如何在eclipse开发loadrunne ...
- 测试开发Python培训:抓取新浪微博抓取数据-技术篇
测试开发Python培训:抓取新浪微博抓取数据-技术篇 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的se ...
- WebService基础学习(三)—CXF
一.什么是CXF? Apache CXF = Celtix + Xfire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF 了,以下简称为 CXF.Apache ...
- C#中的DateTime是值类型还是引用类型
近期遇到了DateTime到底是值类型还是引用类型的疑惑,顺势较深入地了解一下DateTime相关的内容 结论:DateTime是值类型,因为DateTime是结构体,而结构体继承自Syste.Val ...
- 课堂博客-----TreeView+++++XML形成博客
什么是XML? 解析:XML:Extensible Markup Language(可扩展标记语言) HTML:HyperLink Text Markup Language(超文本标记语言) xml ...
- js原型对象
原型对象是什么? 在js中,每一个创建的的函数都会有一个prototype属性,这个属性指向一个对象,这个对象就是原型对象 function lla(){} console.log(lla.proto ...
- php变量布尔值验证
使用 PHP 函数对变量 $x 进行比较 表达式 gettype() empty() is_null() isset() boolean : if($x) $x = ""; str ...