如何正确的覆盖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.对于对象中每个关键域 ...
随机推荐
- 关于本科毕业论文《Laguerre小波在数值积分与微分方程数值解中的应用》存在的问题与小结
本科的毕业设计<Laguerre小波在数值积分与微分方程数值解中的应用>是通过Laguerre小波函数来近似表达某个需要求积分或解微分方程的函数,将原函数很难求得函数用小波函数表达出来,这 ...
- spatial-temporal information extraction典型方法总结
==================================== 咳咳咳 由于科研的直接对象就是video sequence,所以,如何更好地提取spatial-temporal inform ...
- Leetcode——171.宝石与石头
水题: 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头. S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石. J 中的字母不重复,J 和 S中的所有字符 ...
- 实验二 合作:王宏财 http://www.cnblogs.com/wanghongcai/
package 四则运算; import javax.swing.JFrame; import javax.swing.JButton; import javax.swing.JOptionPane; ...
- HDOJ2013_蟠桃记
水题 HDOJ2013_蟠桃记 #include<stdio.h> #include<stdlib.h> #include<math.h> #include< ...
- 基于Windows Subsystem for Linux (WSL) 【Ubuntu】在WIN10 Home Edition安装Docker
root@Andy-PC:~# uname -a Linux Andy-PC --Microsoft #-Microsoft Fri Apr :: PST x86_64 x86_64 x86_64 G ...
- js排序方法
function swap(ary, x, y) { if (x === y) return let temp = ary[x] ary[x] = ary[y] ary[y] = temp } //生 ...
- [转帖]以Windows服务方式运行.NET Core程序
以Windows服务方式运行.NET Core程序 原作者blog:https://www.cnblogs.com/guogangj/p/10093102.html 里面使用了NSSM 工具 但是自己 ...
- python中Switch/Case实现
学习Python过程中,发现没有switch-case,过去写C习惯用Switch/Case语句,官方文档说通过if-elif实现.所以不妨自己来实现Switch/Case功能. 方法一 通过字典实现 ...
- Delphi下EasyGrid使用体会
最近在编写软件的时候,非常需要一款支持多表头的StringGrid控件,朋友介绍使用EasyGrid控件,这款控件大概从04年开始就没有再更新,网上有关与它的资料也较少.但是通过其demo,此软件还是 ...