小概
==,hashCode() 与 equals() ,这三个操作在 Java 程序当中满地都是,特别是容器里,如 Map 中的哈希映射与搜索元素就是根据
hashCode() 和 equals() 判断的,所以如何正确的理解和使用显得非常重要,并且在封装类的时候,十分建议通通重写
我们先要知道这个概念,每个线程都有属于自己的 虚拟机栈,虚拟机栈中的元素我们称之为 栈帧,每运行一个方法时,虚拟机会为这个方法创建一个栈帧,并入栈,方法结束后便出栈
那么我们操作的变量有两种
局部变量:存在当前栈帧的局部变量表里,如果是基本数据类型便是值的大小,如果是对象便是一个指向堆内存中对象地址的引用
全部变量:存在方法区中,存储规则一样
所以我们比较的,是 基本数据类型的大小 和 引用地址
a == b
比较规则
当a,b 为对象时,表示两者 引用地址 是否相同,即堆内存中地址是否相同
当a,b 为基本数据类型时,表示两者 数据大小 是否相等
a.equals(b)
假设 a 的对象类型为 A
比较规则
a,b 只能为对象,表示两者 对象属性 是否相等,如 String 就是比较内部维护的 char[] 数组每一个字符是否相等
为了简化比较复杂度,往往会先判断 a == b,如果它们都指向同一个地址,那么两者内容肯定一样,则不需要逐一比较对象内容中的值
我们可以认为,== 和 equals 的推导关系是 充分不必要 的
== 成立则 equals 成立
equals 成立,== 不一定成立
如何比较属性
比如区分两个学生是否是同一个学生,我们其实只需要查看他们的学号是否相同就行了
也就是我们应该比较能唯一标识这个对象的一个甚至多个对象属性,情况完全视不同对象而定
如果 A 未重写 equals()
如果 A 未重写时,调用的是父类的 equals(),还未重写,会检查到 Object,而 Object 是如下比较的
public boolean equals(Object obj) {
return (this == obj);
}
利用 == 号比较对象内容是否相等未必有点草率,因此我们对这个方法应当十分谨慎
如何重写
重写时需注意应当满足如下规则,摘自 《Effective Java》
自反性:x.equals(x)必须返回true
对称性:x.equals(y)与y.equals(x)的返回值必须相等
传递性:x.equals(y)为true,y.equals(z)也为true,那么x.equals(z)必须为true
一致性:如果对象x和y在equals()中使用的信息都没有改变,那么x.equals(y)值始终不变
非null:x不是null,y为null,则x.equals(y)必须为false
在这里建议按以下规则重写
建议判断 a == b,省去没必要的比较
建议先判断 b instanceOf A,再做能能标识唯一对象的一个或多个属性的比较
建议考虑 super.equals(b)
a.hashCode()
该方法返回的是对象的哈希值,主要应用于哈希容器映射时,将所有类型对象映射成整数
如何重写
在这里建议按以下规则重写
建议对能标识唯一对象的一个或多个属性进行 hashCode() 重写
建议利用 jdk 基础封装类的 hashCode()
建议考虑 super.equals(b)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。