等价关系和等价类_确定Java等价性的新时代?
等價關(guān)系和等價類
幾個月前,我讀了一篇題為“確定Java等價性的新時代?”的博客文章。 這在某種程度上與我當(dāng)時在我那令人沮喪的副項目Java :: Geci中開發(fā)的內(nèi)容非常吻合 。 我建議您暫停閱讀,閱讀原始文章,然后再返回此處,即使您知道一定比例的讀者也不會回來。 這篇文章是關(guān)于如何在Java中正確實現(xiàn)equals()和hashCode() ,以及一些有關(guān)應(yīng)該如何實現(xiàn)或應(yīng)該如何實現(xiàn)的思想。 在本文中,我將為那些不閱讀原始文章的人詳細介紹這些內(nèi)容,并補充我的想法。 部分使用Java :: Geci的方式解決了這些問題,并且在本文結(jié)尾處,應(yīng)如何在equals()和hashCode()處理遞歸數(shù)據(jù)結(jié)構(gòu)。 (請注意,就在我閱讀文章的那一天,我也在完善mapper生成器以處理遞歸數(shù)據(jù)結(jié)構(gòu)。這與我實際上正在解決的問題非常共鳴。)
如果您回來甚至沒有讀完原始文章,甚至連Liam Miller-Cushon所引用的JDK信函中標(biāo)題為“ 等價 ”的內(nèi)容,在這里,您都可以從我的角度總結(jié)一下最重要的陳述/從中學(xué)習(xí)文章:
- 手動生成equals()和hashCode()很麻煩。
- 自Java 7以來,JDK就已經(jīng)提供了支持,但是仍然存在方法的代碼,并且必須對其進行維護。
- IDE可以為這些方法生成代碼,但是重新生成它們?nèi)匀徊皇亲詣踊^程,而手動執(zhí)行重新生成是容易出錯的維護過程。 (又名您忘記了運行發(fā)電機)
來自Liam Miller-Cushon的JDK信(標(biāo)題為“ Equivalence ”)列出了equals()和hashCode()實現(xiàn)中的典型錯誤。 值得在更多細節(jié)中重申這些內(nèi)容。 (某些文字被逐字引用。)
- “覆蓋Object.equals(),但不覆蓋hashCode()。 (Object.hashCode的合同規(guī)定,如果兩個對象相等,則在兩個對象中的每個對象上調(diào)用hashCode()方法必須產(chǎn)生相同的結(jié)果。實現(xiàn)equals()而不是hashCode()使得情況不太可能。)”,這是一個菜鳥錯誤,您可能會說您永遠不會犯錯。 是的,如果您是一名高級程序員,但尚未具備較高的智力水平,例如:忘記了牙齒修復(fù)的位置,那么您永遠不會忘記在創(chuàng)建hashCode()時創(chuàng)建hashCode() equals() 。 但是請注意,這是生命中非常短暫的時間。 許多初級人員也構(gòu)成了代碼庫,缺少的hashCode()可能總是潛伏在Java代碼的干草堆深處,我們必須使用所有經(jīng)濟可行的措施來避免它們的不存在。
- “等于無條件遞歸的實現(xiàn)。” 這是一個常見的錯誤,甚至老年人也多次忽略此可能的錯誤。 因為我們使用的數(shù)據(jù)結(jié)構(gòu)通常不是遞歸的,所以這幾乎不是問題。 當(dāng)它們是遞歸的時, equals()或hashCode()方法的粗心的遞歸實現(xiàn)可能會導(dǎo)致無限循環(huán),堆棧溢出和其他不便之處。 我將在文章結(jié)尾討論這個話題。
- “比較不匹配的字段或吸氣劑對,例如a == that.a && b == that.a. “這是一個主題輸入錯誤,很容易像主題->典型那樣被忽略。
- 等于在給定null參數(shù)時拋出NullPointerException的實現(xiàn)。 (它們應(yīng)該返回false。)
- 等于在給定類型錯誤的參數(shù)時拋出ClassCastException的實現(xiàn)。 (它們應(yīng)該返回false。)
- 通過委派給hashCode()來實現(xiàn)equals() hashCode() 。 (哈希經(jīng)常發(fā)生沖突,因此將導(dǎo)致誤報。)
- 考慮未在相應(yīng)的equals()方法中測試的hashCode()中的狀態(tài)。 (相等的對象必須具有相同的hashCode() 。)
- 將引用相等或hashCode()用于數(shù)組成員的equals()和hashCode()實現(xiàn)。 (他們可能打算使用值相等和hashCode() 。)
- 其他錯誤(不在建議的范圍之內(nèi)):使用錯誤,例如比較兩個靜態(tài)不同的類型,或帶有定義的非本地錯誤(例如,覆蓋等號和更改語義,破壞可替換性)
我們?nèi)绾伪苊膺@些錯誤? 一種可能性是增強語言,如所提到的建議所建議的那樣,以便可以以聲明的方式描述方法hashCode()和equals() ,而實際的實現(xiàn)是常規(guī)且麻煩的,由編譯器完成。 這是光明的未來,但我們必須等待。 Java因Swift整合思想而聞名。 當(dāng)實現(xiàn)某些功能時,它將以向后兼容的方式永久保存。 因此,選擇是快速實施(可能以錯誤的方式實施)并永遠使用下去。 或等到業(yè)界完全確定必須以哪種語言實施它,然后只有那時才能實施它。 Java正在遵循第二種開發(fā)方式。
正如我在《 您的代碼是多余的... 》一文中所描述的那樣,這是語言發(fā)展引起的語言短缺。 暫時的短缺問題將在以后解決,但就目前而言,我們必須解決這一短缺問題。
解決這種短缺的方法之一就是代碼生成,這就是Java :: Geci出現(xiàn)的地方。
Java :: Geci是一個代碼生成框架,非常適合創(chuàng)建代碼生成器,以幫助減少針對特定領(lǐng)域問題的代碼冗余。 代碼生成器在單元測試執(zhí)行期間運行,這似乎有點晚了,因為代碼已經(jīng)被編譯。 但是,此問題已通過以下方式解決:如果“測試”的代碼生成了任何代碼并執(zhí)行了編譯,則生成“測試”的代碼將失敗,并且第二次測試也將不再失敗。
旁注:這種工作方式也可能是任何軟件開發(fā)人員都非常熟悉的:讓我們再次運行它,可能會起作用!
從技術(shù)的角度來看,在編程語言發(fā)展不足的情況下,Java :: Geci也是一樣。 出于特定領(lǐng)域的原因,代碼生成與出于語言發(fā)展不足的原因而生成代碼之間沒有技術(shù)上的區(qū)別。 但是,在語言演變問題的情況下,您可能會找到其他也可以解決該問題的代碼生成工具。 要生成equals()和hashCode() ,可以使用集成開發(fā)環(huán)境。 沒有什么比從IDE中選擇菜單并單擊以下命令更簡單了:“ generate equals and hashCode”。
假設(shè)生成的代碼運行良好,這可以解決以上所有問題之一。 唯一的問題是,無論何時更新代碼,它都不會再次運行代碼生成器來更新生成的代碼。 IDE很難與Java :: Geci競爭。 設(shè)置Java :: Geci框架的步驟比單擊幾個菜單項要多。 您需要測試依賴項,必須創(chuàng)建一個單元測試方法,并且必須注釋需要生成器的類,或者作為替代,您必須在包含生成的代碼的代碼中插入一個編輯器折疊塊。 但是,在那之后,您可以忘記生成器,而無需擔(dān)心團隊中的任何開發(fā)人員都忘記了重新生成equals()或hashCode()方法。
帶走
- 為一個類擁有適當(dāng)?shù)膃quals()和hashCode()方法并不像看起來那樣簡單。 手動編寫它們幾乎不是最好的方法。
- 使用生成工具來生成它們,并確保生成的代碼和代碼生成不會出現(xiàn)上述任何常見錯誤。
- 如果只需要Q&D,則使用IDE菜單并生成方法。 另一方面,如果您有一個較大的代碼庫,并且有許多開發(fā)人員在其中工作,并且代碼生成可能需要重新執(zhí)行,則可以使用自動執(zhí)行代碼生成的工具。 示例:Java :: Geci。
- 使用最新版本的工具(例如Java),以免落后于可用技術(shù)。
翻譯自: https://www.javacodegeeks.com/2019/10/a-new-era-for-determining-equivalence-in-java.html
等價關(guān)系和等價類
總結(jié)
以上是生活随笔為你收集整理的等价关系和等价类_确定Java等价性的新时代?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: ps怎么制作动画效果教程(ps怎么制作动
- 下一篇: 测试框架 如何测试私有方法_高效的企业测
