Object类是java的万类之父,其中,equals和hashcode是Object类的2个非常重要的方法。
1. equals方法:
Object类中默认的实现方式是 :
public boolean equals(Object obj) return this == obj
也就是说,只有this 和 obj引用同一个对象,才会返回true。而我们往往需要用equals来判断 2个对象是否等价,而非验证他们的唯一性。这样我们在实现自己的类时,就要重写equals。
那么,按照约定,equals方法要满足以下规则:
- 自反性: x.equals(x) 一定是true;
- 对null: x.equals(null) 一定是false;
- 对称性: x.equals(y) 和 y.equals(x)结果一致;
- 传递性: a 和 b equals , b 和 c equals,那么 a 和 c也一定equals;
- 一致性: 在某个运行时期间,2个对象的状态的改变不会不影响equals的决策结果,那么,在这个运行时期间,无论调用多少次equals,都返回相同的结果。
到此,常见的面试问题就不是问题了。
问:equals相等,两个类一定相等吗?
答曰:默认情况下,equals相等,两个类一定相等;如果重写的话,那就不一定喽。
equals重写的正确姿势:
public boolean equals(Object obj)
{
if (this == obj)
return true;
if ((obj == null) || (obj.getClass() != this.getClass()))
return false;
//能执行到这里,说明obj和this同类且非null。
Test test = (Test) obj;
return num == test.num&& (data == test.data || (data != null && data.equals(test.data)));
}
equals重写的应该避免的姿势:
if((obj == null) || (obj.getClass() != this.getClass()))
return false;
if(!(obj instanceof Test))
return false; // avoid 避免!
避免!仅当没有子类时正确
注:equals方法的参数类型是Object
2. hashcode方法:
这个方法返回对象的散列码,返回值是int类型的散列码。
(HashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,HashCode是用来在散列存储结构中确定对象的存储地址的)。如果没有hashcode,那么就需要调用equals方法进行对比,equals方法实现一般比较麻烦。如果有hashcode,我们可以先根据hashcode方法进行判断,如果相等,再用equals方法对比。
关于hashCode方法,一致的约定是:
- 重写了euqls方法的对象必须同时重写hashCode()方法。
- 如果2个对象通过equals调用后返回是true,那么这个2个对象的hashCode方法也必须返回同样的int型散列码。
- 如果2个对象通过equals返回false,他们的hashCode返回的值允许相同。(然而,程序员必须意识到,hashCode返回独一无二的散列码,会让存储这个对象的hashtables更好地工作)
总结一句话:等价的(调用equals返回true)对象必须产生相同的散列码。不等价的对象,不要求产生的散列码不相同。