本文主要内容:
覆盖equals() 方法需要遵守哪些通用规定
什么时候该重写equals()方法
重写equals()方法有哪些特征
重写一个equals()方法的步骤
-
为什么重写equals()方法时要先重写hashCode()方法
我们知道equals()方法是顶级类 Object下的一个非 final方法,我们在使用的每个Java类都是要继承Object类的,那么任何一个类在覆盖这些方法的时候,都有责任遵守这个约定.
1 、覆盖equals时要遵循的约定
- 类的每个实例本质是唯一的,也就是每个 new Object()这个这个类的实例是唯一一个,在创建一个对象实例则不是相同的
- 不关心类是否提供了逻辑相等的测试功能。使用Random生成随机数时,不需要关系是否生成了两个逻辑数是否相同,直接就是不同的对象
输出:
-
超类已经重写了equals()方法,从超类继承过来的行为对于子类也是合适的。
例如Map实现了equals方法则直接可以使用equals方法比对两个map是否相等
- 类是私有的或是包级别私有的,可以确定它的equals方法永远不会被调用
2、什么时候该重写equals方法
如果类具有自己特有的“”逻辑特性“”,而且超类还没有覆盖equals以实现期望的行为. 及我们不想知道它是否在内存中指向的是否一个对象,我们想判断它的逻辑值是否相等
例如: 一个雇员实体类里面有员工姓名、薪水等,我想知道2个雇员对象是否是逻辑上相等
3.如何重写一个equals方法了
覆盖Object方法中equals方法需要遵循以下几个规范
- 自反性. 对于任何非null的引用值x, x.equals(x)必须返回true. 通俗的讲自己跟自己比较返回true
- 对称性 对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)也必须返回true
- 传递性 对于任何非null的引用值x、y、z,如果x.equals(y)返回true并且y.equals(z)也返回true,那么x.equals(z)也必须返回true
- 一致性 对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一致的返回true,或者一致的返回false
- 非空性 对于任何非null的引用值x,x.equals(null)必须返回false
如何实现一个equals()方法:
- 1.使用==操作符检查“”参数是否为这个对象的引用”
- 2.使用 instanceof 操作符检查"检查参数是否为正确的类型"
- 3.把参数转换成正确的类型
- 4.对于该类中的没给 “关键”域,检查参数中的域是否与该对象中对应的域相匹配相匹配
package com.minglangx.object;
import java.util.Date;
import java.util.Objects;
public class Employee {
private String name;
private double salary;
private Date hireDay;
@Override
public boolean equals(Object obj) {
// 如果为同一对象的不同引用,则相同
if (this == obj) {
return true;
}
// 如果传入的对象为空,则返回false
if (obj == null) {
return false;
}
// // 如果两者属于不同的类型,不能相等 这种情况只能是对象具有相同的实现才能使用
// if (getClass() != obj.getClass()) {
// return false;
// }
if( !(obj instanceof Employee) ) {
return false;
}
// 类型相同, 比较内容是否相同
Employee other = (Employee) obj;
return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay);
}
}
4为什么重写equals方法之前要重写hashCode方法
因为 Object规范中说到: 相等的对象必须具有相等的散列码
因为hashCode散列码的目的是为了HashSet、HashMap、HashTable比较的时候缩小范围空间,它只是返回一个散列整数然后根据散列码去散列桶中查找对象区间。它不保证对象是否是相等的