Java中的对象要怎样才算相等
一、引用相等性与对象相等性
1. 引用相等性
引用到堆上同一个对象的两个引用是相等的,这就是引用的相等性。
如果想要知道两个引用是否相等,可以使用==来比较变量上的字节组合,如果引用到相同的对象,字节组合也会一样:
if (foo == bar){// 两个引用都指向同一个对象 }
2. 对象相等性
堆上的两个不同对象在意义上是相同的,这就是对象的相等性。
两个对象相等的条件是它们的hashCode相等,而且调用以另一个对象为参数的equals时返回true:
if (foo.equals(bar) && foo.hashCode() == bar.hashCode()) {// 两个引用指向同一个对象或者两个对象是相等的 }
我们知道所有的类都继承自Object类,而Object类默认的equals方法是使用==进行比较:
public boolean equals(Object obj) {return (this == obj); }
Object类的hashCode函数:
public native int hashCode();
是一个native函数,而且返回值类型是整形;实际上,该native方法将对象在内存中的地址作为哈希码返回,可以保证不同对象的返回值不同。
因此,要比较两个对象的相等性,首先需要重写equals和hashCode方法。
二、equals()与hashCode()的规范与关系
1. equals()方法
JDK中说明了实现equals()方法应该遵守的约定:
1)自反性:x.equals(x)必须返回true。
2)对称性:x.equals(y)与y.equals(x)的返回值必须相等。
3)传递性:x.equals(y)为true,y.equals(z)也为true,那么x.equals(z)必须为true。
4)一致性:如果对象x和y在equals()中使用的信息都没有改变,那么x.equals(y)值始终不变。
5)非null:x不是null,y为null,则x.equals(y)必须为false。
2. hashCode()方法
JDK中对hashCode()方法的作用,以及实现时的注意事项做了说明:
1)hashCode()在哈希表中起作用,如java.util.HashMap。
2)如果对象在equals()中使用的信息都没有改变,那么hashCode()值始终不变。
3)如果两个对象使用equals()方法判断为相等,则hashCode()方法也应该相等。
4)如果两个对象使用equals()方法判断为不相等,则不要求hashCode()也必须不相等;但是开发人员应该认识到,不相等的对象产生不相同的hashCode可以提高哈希表的性能。
3. equals()与hashCode()的关系
通过上面两点我们可以推出结论,如果有两个对象a,b,如果有:
a.equals(b),则a.hashCode() == b.hashCode()为真,即两个值相等的对象,他们的hashCode一定相等。
反过来则不一定成立。
实际上在Java中,要证明两个对象值相等,只要a.equals(b)为true就可以了。
三、hashCode的作用
总的来说,hashCode()在哈希表中起作用,如HashSet、HashMap等。
当我们向哈希表(如HashSet、HashMap等)中添加对象object时,首先调用hashCode()方法计算object的哈希码,通过哈希码可以直接定位object在哈希表中的位置(一般是哈希码对哈希表大小取余)。如果该位置没有对象,可以直接将object插入该位置;如果该位置有对象(可能有多个,通过链表实现),则调用equals()方法比较这些对象与object是否相等,如果相等,则不需要保存object;如果不相等,则将该对象加入到链表中。
这也就解释了为什么equals()相等,则hashCode()必须相等。如果两个对象equals()相等,则它们在哈希表(如HashSet、HashMap等)中只应该出现一次;如果hashCode()不相等,那么它们会被散列到哈希表的不同位置,哈希表中出现了不止一次。
实际上,在JVM中,加载的对象在内存中包括三部分:对象头、实例数据、填充。其中,对象头包括指向对象所属类型的指针和MarkWord,而MarkWord中除了包含对象的GC分代年龄信息、加锁状态信息外,还包括了对象的hashcode;对象实例数据是对象真正存储的有效信息;填充部分仅起到占位符的作用, 原因是HotSpot要求对象起始地址必须是8字节的整数倍。
四、参考
1. 《Head First Java(第二版)》
2. 详解equals()方法和hashCode()方法
转载于:https://www.cnblogs.com/harrymore/p/9141947.html
Java中的对象要怎样才算相等相关推荐
- Java中,一切皆是对象——java中的对象类型与基本数据类型的区别
起因:取一个list给另一个list赋值,然后在另一个list中取出进行修改.list其中类型为对象时,String时,基本数据类型时. [java中的对象类型与基本数据类型的区别] #声明和实例化 ...
- Java中根据对象的一个或多个属性进行排序
Java中根据对象的一个或多个属性进行排序 使用情景 解决方法:使用一个工具类:ListUtils 具体使用: 创建一个正常实体类,不用实现comparable接口 调用ListUtiles,并用测试 ...
- 【性能优化】面试官:Java中的对象和数组都是在堆上分配的吗?
写在前面 从开始学习Java的时候,我们就接触了这样一种观点:Java中的对象是在堆上创建的,对象的引用是放在栈里的,那这个观点就真的是正确的吗?如果是正确的,那么,面试官为啥会问:"Jav ...
- java中String对象和String变量
2019独角兽企业重金招聘Python工程师标准>>> java中String对象和String变量 (2011-12-27 20:40:27) 转载▼ 标签: it 最近在论坛上看 ...
- Java中的对象序列化操作
文章目录 1 Java中的对象序列化操作 1 Java中的对象序列化操作 首先看一下对象序列化的操作步骤: 创建一个类,继承Serializable接口 创建对象 将对象写入文件 从文件读取对象信息 ...
- 【译】Java中的对象序列化
前言 好久没翻译simple java了,睡前来一篇. 译文链接: http://www.programcreek.com/2014/01/java-serialization/ 什么是对象序列化 在 ...
- java中String对象作为参数传递问题
问题 java中将对象作为参数传递究竟是值传递还是引用传递? 1.基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的. 2.对象作为参数传递时,是把对象在内存中的地址拷贝 ...
- java 监控对象是什么_多线程-Java中的对象监视器是什么意思? 为什么要使用这个词?...
多线程-Java中的对象监视器是什么意思? 为什么要使用这个词? 在阅读有关Java线程的文章时,我经常注意到这样的表达:"当前线程是该对象的监视器的所有者". 我的意思是:线程有 ...
- java中给对象的List集合去重的几种方法(Lambda)
java中给对象的List集合去重的几种方法 前言 一.lambda表达式的去重方式 二.Stream API中的collect去重方法 三.Stream API 中的distinct方法去重 前言 ...
最新文章
- 国家计算机病毒中心发现“网游大盗”新变种
- JasperMES.cn JasperMES.com.cn 我的MES网站
- correct ways to define variables in python
- CSS+JS实现兼容性很好的无限级下拉菜单
- Twitter是什么软件?哪个国家的?怎么使用?免费吗?
- Docker实用指令整理
- Unity UI 动画 工具
- ApriTag2 检测方法
- 经纬度转换成屏幕坐标
- C语言中3种实用的输出格式:%md,%0md,%.mf
- 六种方法实现JavaScript数组去重
- 基础编程题(1~5)
- 串行RapidIO(Serial RapidIO,SRIO):IP核基础知识
- .net WebApi基础
- 简书iOS APP内测邀请
- 【Python零基础入门篇 · 3】:掌握数值类型、进制的转换
- kubernetes云原生纪元:资源管理(k8s)Resource(上)
- Python识别图片出现的问题及解决办法
- 为什么携程“3+2”办公模式能获得众声叫好?
- 星露谷物语json_星露谷物语时间如何调节?
热门文章
- 区块链新经济蓝图及导读pdf_区块链加快产业数字化转型,区块链新零售模式为企业发展加码提速...
- 加减法叫做什么运算_期中备考:数学运算定律、法则与顺序
- 企业网络推广下的B站二次上市:致力于造就国内最具活力和创造力的内容社区...
- 企业网络推广专员浅析是否网站权重越高企业网络推广效果越好?
- 浅析网站优化的站长们应该怎样安排自己的工作内容呢?
- mysql查看死锁并杀掉_查看当前进程,或死锁进程,并能自动杀掉死进程_MySQL
- 计算机专业术语graphui,计算机专业术语英译
- python交换函数_python a,b = b,一个实现?它与C ++交换函数有何不同?
- 如何完美隐藏Disposable的存储和销毁过程(一)
- 关闭swap的危害——一旦内存耗尽,由于没有SWAP的缓冲,系统会立即开始OOM