首先提出这样一个问题:
如果两个对象不相同,他们的hashcode值一定不相等吗?
我们都知道equals和hashcode是object中的方法,java中每一个对象都具有这两个方法。
- equals(object obj):判断两个对象是否“相同”,返回true或false;
1
2
3
|
public boolean equals(object obj) { return ( this == obj); } |
- hashcode():将该对象的内部地址作为一个int值返回
1
|
public native int hashcode(); |
再来看两条关于这两个方法的规范:
- 如果重写equals(object obj)方法,有必要重写hashcode()方法,以确保equals(object obj)方法返回为true的两个对象有相等的hashcode()返回值。也就是说,如果两个对象相同,他们的hashcode值应该相等;
- 如果equals(object obj)方法返回false,即两个对象不“相同”,并不要求这两个对象调用hashcode()方法有不相等的返回值。也就是说,如果两个对象不相同,他们的hashcode可能相等。
当然,上述只是规范。针对规范1,如果重写equals(object obj)返回true,而hashcode()方法返回不相等的值,也是可以编译过的。
这样我们可以作出如下推论:
- 如果两个对象equals,理论上讲他们的hashcode一定相等(至少java环境会这样认为);
- 如果两个对象不equals,他们的hashcode有可能相等;
- 如果两个对象hashcode相等,他们不一定equals;
- 如果两个对象hashcode不相等,他们一定不equals。
看着有点绕,其实原理很简单。我们从推论3和推论4可以预测:
java在判断两个对象是否“相同”时,首先判断他们的hashcode()方法是否返回相等的int值,其次判断equals方法是否返回true。
我们可以写一段简单的代码测试一下:
首先写一个java类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class person { //重写equals方法,始终返回false; @override public boolean equals(object obj) { system.out.println( "判断person的equals" ); return false ; } //重写hashcode方法,始终返回1; @override public int hashcode() { system.out.println( "判断person的hashcode" ); return 1 ; } } |
上述代码中person类重写了equals方法,打印并始终返回false,重写了hashcode方法,打印并始终返回1。
我们都知道map中要求键不能重复,也就是不能“相同”,所以可以写如下的测试类:
1
2
3
4
5
6
7
8
9
10
|
public class testperson { @test public void test(){ map<person,object> map = new hashmap<>(); map.put( new person(), new object()); //放入第1个person-object键值对; system.out.println( "=====================" ); map.put( new person(), new object()); //放入第2个person-object键值对; system.out.println(map.size()); } } |
运行,打印结果如下
判断person的hashcode
=====================
判断person的hashcode
判断person的equals
2
我们来分析一下:
- 当放入第1个person-object键值对时,java会判断map中有没有和当前添加的new person()相同的对象,于是去调用了person的hashcode()方法,得到返回值1,发现此时map中没有相等的hashcode为1的person对象(因为此时map为空),所以不再判断equals方法,将这个键值对放入map中;(推论4:如果两个对象hashcode不相等,他们一定不equals)
- 当放入第2个person-object键值对时,java依然采用相同的判断方式,hashcode()方法判断之后得到返回值为1,发现此时map中有相等的hashcode值的person对象,然后再去判断equals方法,得到返回值false(推论3:如果两个对象的hashcode相等,他们不一定equals),认为这两个对象不相同,于是将第2个键值对也放入map中。执行之后得到map的size为2
所以可以得出结论:
java在判断两个对象是否“相同”时,首先判断他们的hashcode()方法是否返回相等的int值,如果不相等则直接认为他们不“相同”,如果相等,再判断equals方法是否返回true。
针对上述代码,可以在equals方法和hashcode方法中分别打断点,debug运行,这样会看得比较清楚一点。
我们回到最初的那个问题:如果两个对象不相同,他们的hashcode值一定不相等吗?
上述代码中的场景就充分说明两个对象不相同时hashcode值却相等的场景,当然,这是不按照规范操作的情况。所以写代码时一定要按照规范要求的去做,避免不必要的bug
可以试想一下,如果将上述代码中重写equals方法中的始终返回false改为始终返回true,又会是怎样的结果。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对服务器之家的支持。如果你想了解更多相关内容请查看下面相关链接
原文链接:https://blog.csdn.net/hz_940611/article/details/80365983