JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Software Design » Effective Java  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to postflat modego to previous topicgo to next topic
本主題所含的標籤
無標籤
作者 [Effective Java] 條款7 : 覆寫 equals() 時請遵守通用契約 (general contract)
metavige

麥塔.米奇

版主

發文: 2133
積分: 10
於 2003-10-06 12:04 user profilesend a private message to usersend email to metavigereply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
覆寫 equals() 似乎很簡單, 但很多方式都是錯誤的, 經常導致災難性的後果
這句話真是一針見血阿
這就是告訴我們
如果對兩個實體之間的關係並不是很瞭解的人
請不要去覆寫 equals()

而下列的幾種條件如果成立的話, 可以不去覆寫
1.class 的每個實體具有本質唯一性(inherently unique), 比如說 Thread 就是如此
對這些 classes 而言, Object.equals() 所提供的行為完全正確
2.你並不在意 class 是不是有提供邏輯相等性, 比如 java.util.Random
使用者並不期待兩個 Random 實體是否產生同樣的隨積序列
3.某個 superclass 已經覆寫 equals(), 而從該 superclass 繼承而來的行為又已經適任
4.你的 class 是 private or package-private, 而你確定 equals() 永遠不會被呼叫

什麼時候需要覆寫 Object.equals() ?
當 class 具有邏輯相等性的時候, 而不僅僅要看物件是不是完全一致, 而且其 superclass 還沒覆寫 equals 來達到他所期望的行為, 通常這樣的 classes 稱為 value classes
應該就是說
不僅僅是要比較到 reference 是不是同一個, 還得比較到內部的一些數值資料

以下是覆寫 equals() 時的通用契約, 引用自 java.lang.Object

equals()用以實現等價關係(equivalence relation), 並具有以下性質:
.反身性(reflexive) : for any reference x, x.equals(x) must be true
.對稱性(symmetric) : for any reference x,y, if and only if x.equals(y) is true, then y.equals(x) is true
.遷移性(transitive) : for any reference x,y,z, if x.equals(y) is true, and y.equals(z) is true; then x.equals(z) must be true
.一致性(consistent) : for ant reference x,y, x.equals(y) always return true/false - if data do not been changed.
.for non-null reference x, x.equals(null) must be false
請原諒我用簡單拙劣的英文描述這些條文
其實這些條文並不難懂
有點像是一些數學的證明
就好像是 if a=b then b=a 那樣的東西

這邊其實在書中還有將各項性質再加以詳細的描述
在此我就不多提了

那如果有繼承的關係, 想要擴展一個 superclass, 但是又不想覆寫 equals(), 而能夠維持 equals() 契約的方法, 目前似乎是沒有
所以如果有上述的情況, 目前是可以採用 條款14 的建議, 先考慮複合, 在考慮繼承

以下是撰寫高品質 equals() 的要點:
.以 == 運算元檢查引數「是否為自身的 reference」
.以 instanceof 檢查引數是否為正確型別
.將引數轉換為正確型別, 在使用的時候
.對於 class 每一個有意義的欄位, 檢驗引數中的該欄位是否與物件對應的欄位值相等
.當完成 equals() 時, 請反問自己, 他有對稱性嗎? 他有遷移性嗎? 他有一致性嗎?

最後, 注意事項:

.hashCode() 總是應該和 equals() 一塊被覆寫 (參考條款8)
.過分追求等價, 容易陷入困境
.不要在 equals() 宣告式中用其他型別代替 Object


那個第二點實際上面大概就是在說
如果有 alias 的東西
比如說在 unix like 的 OS 裡面有一種 symbolics link
如果每次比較 File 都還得比較到 symlink 實體對應的檔案
那就太累啦∼ 我想這邊大概就是這個意思


reply to postreply to post
請各位新手參考 論壇規範Java 新手 FAQ
話題樹型展開
人氣 標題 作者 字數 發文時間
6557 [Effective Java] 條款7 : 覆寫 equals() 時請遵守通用契約 (general contract) metavige 2100 2003-10-06 12:04
4158 Re:[Effective Java] 條款7 : 覆寫 equals() 時請遵守通用契約 (general contract) gongtow 93 2005-11-01 00:17
» JWorld@TW »  Software Design » Effective Java

reply to postflat modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8