如何正确的覆盖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.对于对象中每个关键域 ...
随机推荐
- 生命游戏&一维细胞自动机 笔记
de 生命游戏是一种简单的聚合模型,展示了事物是如何聚合的,是自动机(CA)模型的一种.由剑桥大学约翰康威发明,其规则为: 1. 每个细胞拥有八个邻居,细胞状态只有存活(黑)和死亡(白)两种: 2.处 ...
- 第三个Sprint ------第五天
显示计算对错代码 package com.app.senior_calculator; import java.math.BigDecimal; import java.util.EmptyStack ...
- HDU 2032 杨辉三角
http://acm.hdu.edu.cn/showproblem.php?pid=2032 Problem Description 还记得中学时候学过的杨辉三角吗?具体的定义这里不再描述,你可以参考 ...
- Open Source CRM
https://www.odoo.com/zh_CN/page/crm 试用: https://none53.odoo.com/web#home https://none.mypscloud.com/ ...
- docker:Dockerfile构建LNMP平台
docker:Dockerfile构建LNMP平台 1.dockerfile介绍 Dockerfile是Docker用来构建镜像的文本文件,包含自定义的指令和格式.可以通过docker buil ...
- [转载]以及部分总结--Linux下创建单机ASM存储的Oracle实例的过程---感谢方总
Linux下单机安装ASM流程总结 一.安装Linux ESXi上传iso镜像至存储目录 创建虚拟机,并且选择主机设备的ISO启动 选择完成时编辑虚拟机设置 配置镜像文件如下: 打开控制台: 并且选择 ...
- centos7切换gnome3桌面与gnome经典桌面
登陆界面选择设置按钮,选择gnome,进行登陆
- PS(光影魔术手)
完成
- Lodop打印控件里SET_PRINT_STYLE和SET_PRINT_STYLEA
LODOP.SET_PRINT_STYLE 对该语句后面的打印项样式设置效果.LODOP.SET_PRINT_STYLEA 针对第一个参数设置的打印项样式设置效果.这两个语句,作用范围不同. 在设置字 ...
- 如何在Anaconda中实现多版本python共存
anaconda中Python版本是3.5,因为爬虫原因,需要Python2.7版本,因此,希望能在anaconda中Python3和Python2共存. 1. 打开Anaconda Prompt,可 ...