1. 背景
String a=new String("123");
String b=new String("123");
我们知道,在java中 a == b 比较的是对象的在内存中的物理地址,equals()方法的作用本来和==相同,也是比较两者的物理地址,但String类重写了equals()方法,于是String类的equals方法变成了比较两个字符串对象的字符串内容是否相等。
2. equals()和hashcode()方法需要同时重写的原因
首先,我们要明白hashCode()方法的作用是确定对象在散列存储结构例如HashMap、HashSet中的存储地址。
注:这个地址不是对象在内存中的真实存储地址,只是在数据结构中的逻辑地址
那么,我们就能知道为什么重写equals()方法同时要重写hashcode()方法了:
因为,如果重写了equals()方法,没有重写hashCode()方法的话,如果a.equals(b),但a的hashCode与b的hashCode不相等,则当我们将a、b同时加入散列存储结构map、set时,就可能出现数据结构中存在两个值相等的对象的情况,从而导致混淆。
示例:
String a=new String("123");
String b=new String("123");
System.out.println(a==b); //false
System.out.println(a.equals(b)); //true
System.out.println(a.hashCode()==b.hashCode()); //true
Set<String>set=new HashSet<>();
set.add(a);
System.out.println(set.contains(b)); //true
以上例子可以看出,虽然a和b不是同一个对象,但是由于表达式a.equals(b)结果是true,所以a的hashCode与b的hashCode相等,两者在set中存储地址相同,在set中加入a后,在set中查询b,返回结果是true。如果仅重写了equals方法,而没有重写hashcode方法,那就有可能出现a.equals(b)==ture,但是set.contais(b)返回的却是false;
综上,重写equals()方法同时尽量也要重写hashcode()方法。
3. 重写equals方法遵循的原则
hashCode并不需要唯一性,但equals必须严格地判断两个对象是否相同。
正确的equals方法有如下特性:
- 自反性:
x.equals(x)一定返回true - 对称性:如果
x.equals(y)为true,那么y.equals(x)也为true - 传递性:如果
x.equals(y)为true、y.equals(z)为true,那么x.equals(z)也为true - 一致性:如果
x和y中用于等价比较的信息没有改变,那么x.equals(y)无论调用多少次,结果都一致 - 任何不是
null的x,x.equals(null)一定返回false
4. equals与hashCode的相关规定
之所以有规定,是为了使诸如HashMap这样的哈希表正常使用。具体规定如下:
equals相等,hashcode一定相等。equals不等,hashcode不一定不等。hashcode不等,equals一定不等。hashcode相等,equals不一定相等。