說說Java裏的equals(中)- Java那些事兒

面向對象 - Java那些事兒 一文中,咱們後續留了一個話題,引入了Set,咱們知道Set裏面的元素是不能夠重複的,話很少說,上代碼:編程

精簡了上一章中的Person類,保留了isSame()方法;ide

想必你們看到相似的代碼開始懷疑筆者是否是又挖坑讓大夥跳了吧,來看一下結果。post

沒錯,有坑,一樣是對象,都是放到了set中,一個打印size()是1,另外一個打印size()是2。面向對象 - Java那些事兒 一文中,咱們在Person這個類,雖然寫了一個isSame()方法來判斷業務上是否相等,看上去是解決了當時的問題,然而不知不覺的爲本身挖了坑。假設咱們如今正在給用戶批量發工資,張三出現了兩次,雖然咱們用Set去了重,但仍是會給張三發兩次工資。測試

在Java程序中,有不少的「公約」,咱們稱之爲編程規範,遵照這些規範實現你的代碼,會讓你避開不少坑。要判斷兩個對象的內容是否相等,不要本身寫方法(isSame())去判斷,而是應該重寫父類的 equals方法(這裏的父類是Object),在說說Java裏的equals(上) - Java那些事兒,咱們說過String重寫了equals()方法,因此這兒打印size結果是1,而Person沒有重寫,所以Set無法判斷這兩個"張三"是不是同一我的,打印size結果是2。3d

咱們再看如下代碼:cdn

結果固然是全是false(這個應該沒人能答錯了吧),看結果對象

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

看起來沒問題,別忘 了,若是是重寫方法,咱們在方法上要加上@Override註解,加上該註解,編譯器會幫你檢查是否真的覆蓋了父類的方法。編譯一下,竟然報錯了。繼承

原來咱們跟本就不是重寫(覆蓋)了父類的equals方法,而是本身又寫了一個參數爲Person的equals方法,根本不是重寫,只是重載了父類的方法而已。開發

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

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

下面咱們正確的覆蓋一下。

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

運行一下,perList裏面咱們只添加person1,並無添加person2,但執行perList.contains(person2)打印的結果竟然是true(List裏面包含了person2),只由於重寫了equals()方法,注意:pSet.contains(person2))依舊是false。

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

很明顯,Person這個類在重寫equals()方法後,雖然已經支持List,但還不支持Set。要完美支持HashMap,HashSet,LinkedHashMap,ConcurrentHashMap等這些類,不但要重寫equals方法,還須要重寫hashCode()方法。

如今咱們在Person類裏重寫一下hashCode()方法

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

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

注:本文中提到的HashMap,HashSet,LinkedHashMap,ConcurrentHashMap,List,hashCode等後續專欄會講解。


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

回答評論區的問題

在文中一開始的示例中,person1,person2並非同一個對象,默認equals方法是繼承自Object的,也就至關於==,若是沒有額外的需求明確name相同就視爲同一個對象處理,就沒有必要去重寫equals方法了。

注:本專欄文章首發於公衆號:saysayJava。全部示例代碼均已上傳至公衆號,須要請關注下載。

若是喜歡本系列文章,請爲我點贊或順手分享,您的支持是我繼續下去的動力,您也能夠在評論區留言想了解的內容,有機會本專欄會作講解,最後別忘了關注一下我。

轉載無限歡迎,但請註明「做者」和「原文地址」。轉載請在文中保留此段,感謝您對做者版權的尊重。如需商業轉載或刊登,請聯繫做者得到受權。


上一篇:面向對象 - Java那些事兒

下一篇:ArrayList初始化 - Java那些事兒

相關文章
相關標籤/搜索