如何正确的覆盖equals和hashCode
一、Object所有的非final方法
- public boolean equals(Object obj)
- public native int hashCode()
- public String toString()
- protected native Object clone() throws CloneNotSupportedException
- protected void finalize() throws Throwable { }
类的方法前加final关键字,说明该方法不能被该类的子类重写。
二、equals方法和hashCode方法
1、什么时候需要覆盖equals方法
如果类具有自己特有的“逻辑相等”概念(不同于对象等同的概念),而且超类还没有覆盖equals以实现期望的行为,这时候我们就需要覆盖equals方法。
2、如何正确的覆盖equals方法
equals方法实现了等价关系:自反性,对称性,传递性,一致性,非空性(x.equals(null)返回为false)
- 使用==操作符检查“参数是否为这个对象的引用”,如果是,则返回true。
- 使用instanceof操作符检查“参数是否为正确的类型”,如果不是,则返回false。
- 把参数转换成正确的类型。
- 对于该类中的每个“关键”阈,检查参数中的阈是否与该对象中对应的阈相匹配。
class Student{ private String name;
private int age;
private double height;
@Override
public boolean equals(Object obj) {
//使用==操作符检查“参数是否为这个对象的引用”
if(this==obj)
return true;
//使用instanceof操作符检查“参数是否为正确的类型”
if(!(obj instanceof Student))
return false;
//把参数转换成正确的类型。
Student student=(Student) obj;
//对于该类中的每个“关键”阈,检查参数中的阈是否与该对象中对应的阈相匹配。
return this.name==student.name && this.age==student.age && this.height==student.height;
}
}
1、编写完成equals方法之后,应该问自己三个问题:它是否对称的、传递的、一致的。
2、不要将equals声明中的Object对象替换为其他的类型
public boolean equals(Student obj)
这样相当于重载了equals方法,而非是覆盖。
3、覆盖equals时总要覆盖hashCode
HashCode有一条约定如下:
如果两个对象根据equals(Object)方法比较是相等,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。
下面给出一种简单的解决办法:
- 把某个非零的常数值,比如说17,保存在一个名为result的int类型的变量中。
- 对于对象每个关键域f(指equals方法中涉及的每个域),完成以下步骤:
- 如果该域是boolean类型,则计算(f ? 1 : 0)。
private boolean flag=true;
int boolTemp=flag?0:1; - 如果该域是byte、char、short或者int类型,则计算(int)f。
- 如果该域是float类型,则计算Float.floatToIntBit(f)。
- 如果该域是long类型,则计算(int)(f ^ (f >>> 32))。
- 如果该域是double类型
private double height;
long heightBits=Double.doubleToLongBits(height);
int heightTemp=(int)(heightBits ^ (heightBits >>> 32)); - 如果该域是一个对象引用,并且该类的equals方法通过递归调用equals的方式来比较这个域,则同样为这个域递归调用hashCode。
private String name;
int stringTemp=this.name.hashCode();
完整的Student类:
class Student{
private String name;
private int age;
private double height;
@Override
public boolean equals(Object obj) {
//使用==操作符检查“参数是否为这个对象的引用”
if(this==obj)
return true;
//使用instanceof操作符检查“参数是否为正确的类型”
if(!(obj instanceof Student))
return false;
//把参数转换成正确的类型。
Student student=(Student) obj;
//对于该类中的每个“关键”阈,检查参数中的阈是否与该对象中对应的阈相匹配。
return this.name==student.name && this.age==student.age && this.height==student.height;
} @Override
public int hashCode() {
//初始化
int result=17;
//String类型
result=this.name.hashCode()+result;
//int类型
result=this.age+result;
//double类型
long heightBits=Double.doubleToLongBits(height);
int heightTemp=(int)(heightBits ^ (heightBits >>> 32));
result=heightTemp+result;
//返回
return result;
}
}
如何正确的覆盖equals和hashCode的更多相关文章
- 如何正确的重写equals() 和 hashCode()方法
比较两个Java对象时, 我们需要覆盖equals和 hashCode. public class User{ private String name; private int age; priva ...
- Java提高篇——equals()与hashCode()方法详解
java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...
- 大杂烩 -- equals、hashCode联系与区别
基础大杂烩 -- 目录 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Equals 1.默认情况(没有覆盖equals方 ...
- 集合框架比较两个对象是否相同(equals和hashCode方法)
package com.dcz.hashset; import java.util.HashSet; import java.util.Set; /** * HashSet是接口最常用的实现类,顾名思 ...
- 【Java实战】源码解析为什么覆盖equals方法时总要覆盖hashCode方法
1.背景知识 本文代码基于jdk1.8分析,<Java编程思想>中有如下描述: 另外再看下Object.java对hashCode()方法的说明: /** * Returns a hash ...
- 第9条:覆盖equals时总要覆盖hashCode
在每个覆盖equals方法的类中,也必须覆盖hashCode方法.否则,会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常工作,包括HashMap,Hash ...
- 覆盖equals的时候总要覆盖hashCode
import java.util.HashMap; public class Student { private String name ; private String id; public Stu ...
- Item 9 覆盖equals时总要覆盖hashCode
为什么覆盖equals时,总要覆盖hashCode? 原因是,根据Object规范: 如果两个对象根据equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCod ...
- EffectiveJava(9)覆盖equals是总要覆盖hashCode
覆盖equals是总要覆盖hashCode 通过散列函数将集合中不相等的实例均匀的分布在所有可能的散列值上 1.把某个非零的常数值保存在一个名为result的int类型变量中 2.对于对象中每个关键域 ...
随机推荐
- guthub第一次作业连接及心得体会
https://github.com/12wangmin/ GitHub的本意是旨在成为一种开放的软件协作平台,但它目前已成为一个巨大的综合性的平台,其作用远远超过单纯地开源代码.它现在在艺术家.建筑 ...
- [2017BUAA软工]第零次博客作业
第一部分:结缘计算机 1. 你为什么选择计算机专业?你认为你的条件如何?和这些博主比呢?(必答) 当年高考前在专业这件事上纠结了好久,因为我对于大学各个专业具体学什么都不甚了解,于是就迟迟没有明确的目 ...
- IP工具类
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletReques ...
- Windows10下Docker监控管理工具:Hyper-V管理器
用Hyper-V管理器监控管理Docker,看到最新的MobyLinuxVM了. 今天启动Docker,出现内存不足的问题,调节内存配置即可.
- MYSQL CASCADE DELETE 引发的思考
MYSQL CASCADE DELETE :级联删除.这个概念还是学习Oracle时得到的. 就是主键记录删除时,相关的有外键的表里的记录,也删除. https://dev.mysql.com/doc ...
- SQLPLUS SQLCMD连接管理oracle sqlserver的简单用法
1. SQLPLUS 与plsql一样,其实不需要安装oracle客户端,只要是有sqlplus的即时客户端 以及将目录放置到path或者是相应的oralce_home变量中即可. 打开运行cmd s ...
- Babel安装在本地并用webstrom由ES6转Es5
1进入到根目录 2安装babel npm install babel-cli --save-dev 3安装其他库 npm install --save-dev babel-preset-env 4创 ...
- Jquery 组 表单验证
<!DOCTYPE html><html lang="zh-cn"><head> <meta charset="utf-8&qu ...
- K3CLOUD安装教程
1.安装SQLSERVER2008 2.安装K3CLOUD安装包,此处各种安装iis,tomcat,ftp等环境,有过it经验的应该都能自己搞定,不详细赘述 3.进入管理中心,进行设置,默认为127. ...
- Centos7安装Splash
前言 最近在用Scrapy抓取一个网站数据,其中有个页面需要执行js脚本才能加载,所以需要用到Splash. 官网地址:https://splash.readthedocs.io/en/stable/ ...