Java hashCode() 与 equals ()
hashCode() 与 equals() 是定义在 Object 类中的方法, Java 中所有类都默认继承自 Object 类。但是当你声明一个类的时候并不用这样写:
public class Employee extends Object
如果没有明确的指出超类,就默认超类为 Object 类。因此,任何类都能调用继承自 Object 的 hashCode() 与 equals() 方法
hashCode() 与 equals() 的用法
equals()方法
equals() 用于判断两个对象是否相等,Object 类中的 equals() 比较两个类的引用是否相等,如果引用相等,就返回true,否则返回 false。
有些时候,默认的 equals() 方法并不适用,例如,我们根据员工的ID来判断两个员工对象是否相等。但是默认的 equals() 方法只是比较两个对象的引用。 所以我们需要在 Employee 类中重写 equals() 方法,让 equals() 方法比较两个员工的 ID 。
public class Employee {
private String name;
private int ID;
//Getter-Setter
@Override
public boolean equals(Object otherObject) {
Employee other = (Employee) otherObject;
// 比较它们的ID是否相等
return this.getID() == other.getID();
}
}
这样的改动并不完美,我们加入一些优化措施
@Override
public boolean equals(Object otherObject) {
Employee other = (Employee) otherObject;
//== 比较连个对象是否指向用一个引用
if(this==otherObject)return true;
//检测另一个类是否为null
if(otherObject==null) return false;
//检测Class是否相等
if(this.getClass()!=otherObject.getClass())
return false;
// 比较它们的ID是否相等
return this.getID() == other.getID();
}
实现equals时有个常见的错误:
这个方法接收参数的类型是Employee,因此,它并没有覆盖Object类中的equals方法,这个方法与Object类中的equals() 毫无关系。
//...
public boolean equals(Employee otherObject)
//...
为了避免这种低级错误,建议用 @Override标记覆盖超类的方法。
@Override
public boolean equals(Object otherObject)
重写equals()方法需要遵循的原则:
- 若x.equals(y)返回true 则y.equals(x)应当返回true。
- x.equals(y)返回true 且 y.equals(z)返回true,则x.equals(y)应当返回true。
- 对于任意不为null 的对象x, x.equals(null)应当返回false。
hashCode() 方法
散列码(hashcode) 是由对象导出的一个整型值。默认的 hashCode() 方法根据对象在内存中的地址,计算对象的散列码。一般来说,如果a 和 b 是两个不同的对象,a.hashCode() 与b.hashCode() 肯定不同。
如果重写了equals方法,请一定不要忘了重写 hashCode() 方法,java 官方文档中是这样写的:
如果两个对象用equal() 方法比较时相等,那么它们的 hashCode() 方法应该返回同样的值 。
我们按照要求,在 Employee 中重写 hashcode 方法
@Override
public int hashCode()
{
final int PRIME = 1;
int result = 1 + getId();
return result;
}
注意hashCode 的实现不唯一,只要能实现上面的要求就行
如果忘记重写 hashCode() ,可能会带来难以预料的后果,比如:
public static void main(String[] args) {
Employee e1=new Employee();
Employee e2=new Employee();
e1.setId(123);
e2.setId(123);
//打印结果为true
System.out.println(e1.equals(e2));
Set<Employee> hashset = new HashSet<Employee>();
hashset.add(e1);
hashset.add(e2);
//打印结果为2
System.out.println(hashset.size());
}
在例子中,e1和e2的id 都被设置为123,它们是两个相等的对象,因为上一步我们已经重写了 equals() 方法,该方法比较两个对象的id是否相等,相等则返回true,否则返回false。
但是当我们尝试将e1,和e2放入set中的时候,问题出现了,我们知道set中不能放置重复的元素,但是在这里 set 中却能够同时放入e1和e2,这显然不符合我们的逻辑。
至此,hashCode() 与 equals () 的基本用法介绍完毕。