天天看點

說說equals() (中)

說說equals() (中)

看看下面代碼,猜猜結果

說說equals() (中)

想必大家看到類似的代碼開始懷疑筆者是不是又挖坑讓大夥跳了吧,來看一下結果。

說說equals() (中)

沒錯,有坑,同樣是對象,都是放到了set中,一個列印size()是1,另一個列印size()是2。假設我們現在正在給使用者批量發工資,張三出現了兩次,雖然我們用Set去了重,但還是會給張三發兩次工資。

在Java程式中,有很多的“公約”,我們稱之為程式設計規範,遵守這些規範實作你的代碼,會讓你避開很多坑。要判斷兩個對象的内容是否相等,不要自己寫方法(isSame())去判斷,而是應該重寫父類的 equals方法(這裡的父類是Object),我們知道String重寫了equals()方法,是以這兒列印size結果是1,而Person沒有重寫,是以Set沒法判斷這兩個”張三”是否是同一個人,列印size結果是2。

我們再看以下代碼:

說說equals() (中)

結果當然是全是false(這個應該沒人能答錯了吧)

下面我們像String一樣,重寫一下Person的equals方法。

說說equals() (中)

看起來沒問題,别忘 了,如果是重寫方法,我們在方法上要加上@Override注解,加上該注解,編譯器會幫你檢查是否真的覆寫了父類的方法。編譯一下,居然報錯了。

說說equals() (中)

原來我們跟本就不是重寫(覆寫)了父類的equals方法,而是自己又寫了一個參數為Person的equals方法,根本不是重寫,隻是重載了父類的方法而已。

重載:就是在同一個類中,方法的名字相同,但參數個數、參數的類型不同。

重寫:它是指子類和父類的關系,子類重寫了父類的方法,但方法名、參數類型、參數個數必須相同

下面我們正确的覆寫一下。

說說equals() (中)

我們寫一段測代碼測試一下,這裡我們引入了List。

說說equals() (中)

運作一下,perList裡面我們隻添加person1,并沒有添加person2,但執行perList.contains(person2)列印的結果居然是true(List裡面包含了person2),隻因為重寫了equals()方法,注意:pSet.contains(person2))依舊是false。

說說equals() (中)

再執行本文開始那段代碼,不出所料,問題依舊

說說equals() (中)

很明顯,Person這個類在重寫equals()方法後,雖然已經支援List,但還不支援Set。要完美支援HashMap,HashSet,HashSet,LinkedHashMap,ConcurrentHashMap等這些基于散列的集合類,不但要重寫equals方法,還需要重寫hashCode()方法。

現在我們在Person類裡重寫一下hashCode()方法

說說equals() (中)

再執行一下,終于看到想要的結果了。

說說equals() (中)

再執行一下本開始那段代碼,已經是我們想要的結果了。

說說equals() (中)

總結:當我們在實際業務中需要重寫(覆寫)equals方法時,根據規範,我們一定要重寫(覆寫)hashCode方法。在實際開發過程中,不建議一上來就重寫equals方法,除非你有特殊的需求。

在文中一開始的示例中,person1,person2并不是同一個對象,預設equals方法是繼承自Object的,也就相當于==,如果沒有額外的需求明确name相同就視為同一個對象處理,就沒有必要去重寫equals方法了