覆蓋equals時請遵照通用約定(8)

一、覆蓋equals方法需謹慎,可能會致使嚴重後果java

  • 最容易避免的方式就是,不去覆蓋

二、覆蓋equals 方法指望你知足:sql

(1)類的每一個實例本質上都是惟一的數組

  • 表明活動實體而不是值得類確實如此
  • Object 的equals 本質調用的是 ==
  • 對於像String 類就是作值判斷,和這裏要求的惟一不是一種狀況

(2)不關心類是否提供了」邏輯相等「的測試功能ide

  • 在類的每一個實例都與自身相等狀況下,從Object繼承已經足夠了

(3)超類已經覆蓋了equals 方法,從超類繼承的equals方法對於子類也是合適的性能

  • Set實現都從AbstractSet 繼承equals 實現,Map、List 也是

(4)類是私有的 或包級私有的 能夠保證equals 方法永遠不會被調用測試

  • 未聲明(包級私有)、 public、protected、private
  • 類的訪問權限:

  • 要咱們用代碼來保證,以防其被之外調用

三、何時須要覆蓋equals 方法:優化

  • 類具備本身獨有的邏輯相等概念(不一樣於對象等同概念)
  • 父類又沒有實現指望的 equals 行爲
  • 一般指 」值類「 如String、Integer、Date等
  • 覆蓋equals 方法,還須要使類的實例能夠作map的key ,集合(set)的相關要求
  • 上述map的key 要求不相等,集合(set)不能有重複項:都是equals判斷的
  • 實際上,上述先用hashcode判斷,而後再equals 比較,提升效率

四、實例受控<1條>確保每一個值最多存在一個對象的狀況,不用覆蓋.net

  • 好比:枚舉類型(邏輯相等等同於對象等同)

五、覆蓋equals 方法,遵照通用約定:code

(1)自反性:任何非null 值,x.equals(x) 必須返回true對象

(2)對稱性:任何非null 值,x.equals(y)==true,則必須知足y.equals(x)==true

  • 以下紅框所示,該類實例和String 實例比較時
  • caseIns.equals(str)==true,可是 str.equals(caseIns)==false

(3)傳遞性:任何非null 值,x.equals(y)==true,x.equals(z)==true,則必須知足x.equals(y)==true

  • 咱們沒法擴展可實例化類的同時,既增長組件,又保留equals 方法的約定

ColorPoint 繼承自Point ,多了一個color 屬性

覆蓋equals 方法1:

  • 該方法問題在於,沒法比較 p.equals(cp)==true, cp.equals(p)==false 沒有實現傳遞性

覆蓋equals 方法2:

  • instanceof具備傳遞性(實例 的類、父類、實現接口 都知足)
  • 實現了對稱性,沒有實現傳遞性

好比:

  • p1.equals(p2)==true,p2.equals(p3)==true, 可是:p1.equals(p3)==false

這裏可使用組合的方式知足上述需求:

  • java.sql.Timestamp 擴展了java.util.Date 增長了域,不知足equals 約定,是很差的案例

可是,咱們能夠在抽象類的子類中添加新的組件、而且不違反equals 約定

(4)一致性;任何非null 值,只要equals 比較所用信息沒變,屢次調用 都能獲得 x.equals(y)==true

  • equals 方法永遠不要依賴不可靠資源
  • java.net.URL的equals 方法依賴於主機IP地址的比較,IP地址是不靠譜資源,由於IP地址會變

(5)非空性:對於任何非null 值,必有 x.equals(null)==false

  • 下述 判空是沒必要要的

  • 判空沒必要要緣由以下,即類型判斷的存在
  • 若是 o 是空,instanceof 返回的都是false,因此不須要單獨判空

有許多類,包括全部集合類,都依賴於傳遞給他們的equals 方法是否聽從約定

六、高質量equals 方法實現訣竅:

(1)使用== 檢查 "參數是否爲這個對象的引用"

  • 僅僅是性能上的一種優化

(2)使用instanceof 檢查 」參數是否爲正確的類型「

  • 也能夠是接口

(3)把參數轉換成正確的類型

(4)檢查該類中的每一個」關鍵「域,檢查參數中的域是否與該對象中對應的域相匹配

  • 若是是接口,必須經過接口方法訪問每個域
  • 類的話,根據可訪問性訪問
  • 對於非(float、double)浮點的基本類型,可採用== 比較
  • 對於浮點數,可採用Float.compare、Double.compare比較
  • 浮點數特殊處理是必要的,由於存在Float.NaN、-0.0f等特殊常量(Double相似)
  • 數組域,對每一個元素比較;或者採用Arrays.equals方法比較
  • 有些引用域null 是合法的,採用下述比較:

  • 相同的對象引用,下述方法更快:

  • 域的比較比等同比較複雜得多,可保存」範式「 以儘可能使用低成本精確比較

域的比較順序也會影響性能

  • 優先比較開銷最低的域、最可能不一致的域,同時知足兩者

(5)完成equals 方法,再三確認是否 對稱、一致、傳遞

  • 還有 自反性、非空性,這倆通常自動知足
  • 覆蓋equals  時,總要覆蓋hashcode<9條>
  • 不要企圖讓equals 過於智能 不要過分準求各類等價關係

如:File 類的指向同一個文件的各類符號連接相等,File 沒有那麼作

  • 不要將equals 參數中的Object 替換成其餘類型
  • 以下所述,這樣並無覆蓋Object的equals 方法,僅僅重載了equals 方法
  • 這樣在某些時候提高性能,但複雜度加大,得不償失

  • 使用@Override 編譯器會告訴你問題

相關文章
相關標籤/搜索