首先提出這樣一個問題:
如果兩個對象不相同,他們的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