欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

淺談java重寫equals方法的種種坑

重寫java object類的equals方法

創(chuàng)新互聯(lián)專注于揭陽企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城網(wǎng)站定制開發(fā)。揭陽網(wǎng)站建設(shè)公司,為揭陽等地區(qū)提供建站服務(wù)。全流程按需求定制網(wǎng)站,專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

  • 覆蓋equals方法請遵守約定
  • 什么情況下要覆蓋equals方法
  • 容易違反的對稱性
  • 不易察覺的傳遞性

覆蓋equals請遵守通用約定

似乎覆蓋equals方法看起來似乎是一件平常甚至極其簡單的事情,
但是有許多覆蓋方式會導(dǎo)致錯誤,并且會表現(xiàn)出超出預(yù)期的行為,
而有可能數(shù)小時也無法找到錯誤的位置。(比如說把參數(shù)改成了非Object類型)

1. 類的每一個實例在本質(zhì)上都是唯一的

 ( 從內(nèi)存的角度來講是這樣的),對于代表活動而不是值(value)的類來說更是如此,
 例如Thread。
 Object提供equals的實現(xiàn)對于這些類來說是正確的行為

2. 類沒有必要提供“邏輯相等”的測試功能

3.超類已經(jīng)覆蓋了equals方法,超類的行為對于子類來說同樣也是合適的

4.類是私有的或者是包級私有的,可以確定它的equals方法永遠(yuǎn)不會被外界調(diào)用

如果非常想規(guī)避風(fēng)險,可以覆蓋equals方法,
來確保來自O(shè)bject或者超類的方法永遠(yuǎn)不會被意外調(diào)用。

那么什么時候應(yīng)該覆蓋equals方法

如果類具有自己特有的“邏輯相等”概念(不同于對象等同的概念)
而且超類沒有覆蓋equals方法。這通常屬于"值類"(value class)的情形

 例如 一個圓 Circle類,內(nèi)有一個私有的成員變量radius半徑
可以認(rèn)為,radius相等代表了兩個實例在邏輯上相等(或許可以再加上坐標(biāo))

 再看String類,程序員在利用equals方法比較值對象的引用時,
更希望知道它們邏輯上是否相等,而不希望知道它們到底是不是同一個對象

為滿足要求,不僅必須覆蓋equals方法,
而且這樣做也使得這個類的實例
可以被用作映射表 (map) 的鍵 (key) ,或者集合set的元素,
使其表現(xiàn)出符合預(yù)期的行為

注意:有一種“值類”不需要覆蓋equals方法
即實例受控,甚至于單例模式,
確保每個實例的“值”至多只存在一個對象,甚至僅能存在一個實例
(好像太嚴(yán)格了,不過只能存在一個對象有什么可比的呢,就像客戶端只能有一個連接服務(wù)器的socket類實例一樣)

覆蓋equals時請遵守通用約定

自反性,對稱性以及傳遞性是最基礎(chǔ)的約定

x.equals(x) = x.equals(x) (好像很傻)
x.equals(y) = y.equals(x)(這也是最容易出現(xiàn)問題的地方)
x.equals(y) = y.equals(z) 那么x.equals(z) == true

一致性:

對于任何非null引用值x和y,只要equals方法的比較操作在對象中引用的信息沒有被修該,多次調(diào)用x.equals(y)返回的結(jié)果一致

對于任何非null的引用值x,x.equals(null)必須返回false
下面是一個不區(qū)分大小寫字符串類的定義(注意 是反例?。∵`反了對稱性)

public class CaseInsensitiveString {

 private final String s;//存有不可變字符串s

 public CaseInsensitiveString(String s) {
  this.s = s;
 }

 @Override //重寫equals方法,請注意參數(shù)為Object
 public boolean equals(Object o) {
  if (o instanceof CaseInsensitiveString)//判斷傳入的是同類型的參數(shù)
  {
   return s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
  }
  if (o instanceof String) {
   return s.equalsIgnoreCase(((String) o));
  }
  return false;
 }
}

注意:equals方法中的參數(shù)Object o ,一定不要定義成其他類型?。?/p>

在絕大多數(shù)情況都要加上一句instanceof 來給o 賦予類型?。?!

這個類的equals方法看起來設(shè)計的很有想法,不僅和自身比較,也希望和String類型進(jìn)行比較。

 //也確實看起來實現(xiàn)了功能
 public static void main(String[] args)
 {
  //不區(qū)分大小寫的字符串Point
  CaseInsensitiveString cis = new CaseInsensitiveString("Point");
  String s = "point";
  System.out.printf(cis.equals(s)+"");//true
  
 }

但是 s.equals(cis)卻返回了false

 //s.equals(cis)卻返回了false
 public static void main(String[] args)
 {
  CaseInsensitiveString cis = new CaseInsensitiveString("Point");
  String s = "point";
  System.out.printf(cis.equals(s)+"");//true
  System.out.printf(s.equals(cis)+"");//false
 }

雖然CaseInsensitiveString類中的equals方法知道普通的字符串對象
但是String類中的equals方法并不知道不區(qū)分大小寫的字符串,
導(dǎo)致了超出預(yù)期的錯誤
顯然違反了對稱性。

一旦違反了equals約定,當(dāng)其他對象面對你的對象是,你完全不知道這些對象的行為會怎樣

為了解決這個問題,只需要把企圖和String互相操作的代碼刪除就可以了

public class CaseInsensitiveString {

 private final String s;//存有不可變字符串s

 public CaseInsensitiveString(String s) {
  this.s = s;
 }

 @Override //重寫equals方法,請注意參數(shù)為Object
 public boolean equals(Object o) {
  if (o instanceof CaseInsensitiveString)//判斷傳入的是同類型的參數(shù)
  {
   return s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
  }
  /*刪除掉的與String互操作的代碼*/
  return false;
 }

}

考慮這樣一種情況

有一個坐標(biāo)類,內(nèi)有成員變量x和y
并提供equals方法

public class Point {
 private final int x;
 private final int y;
 public Point(int x,int y)
 {
  this.x=x;
  this.y=y;
 }
 @Override
 public boolean equals(Object o )
 {
  if(o instanceof Point)
  {
   Point p = (Point)o;
   return (this.x == p.x && this.y==p.y);
  }
  return false;
 }
}

好像簡單到不能再簡單的定義
那么擴展(繼承)一下,為這個點添加顏色信息

public class ColorPoint extends Point{
 private final Color color;
 public ColorPoint(int x,int y,Color color)
 {
  super(x,y);
  this.color=color;
 }
}

現(xiàn)在考慮一下

equals方法是什么樣的呢?
如果子類ColoePoint完全不提供equals方法,而是直接使用父類的equals方法
在equals做比較的時候顏色信息就被忽略掉了。
雖然這么做不會違反equals約定
但顯然是無法接受的。

那么就重寫一個equals方法。只有當(dāng)坐標(biāo)點x,y相同且顏色也相同時
equals才返回true

public class ColorPoint extends Point{
 private final Color color;
 public ColorPoint(int x,int y,Color color)
 {
  super(x,y);
  this.color=color;
 }
 @Override
 public boolean equals(Object o)
 {
  if(o instanceof ColorPoint)
  {
   return (super.equals(o)&& this.color==
   ( (ColorPoint) o ).color);//使用父類的equals方法
  }
  return false;
 }
}

這個方法的問題在于,比較普通點(沒有顏色的Point實例)和
有色點(ColorPoint實例)比較,以及相反的情況時可能會得到不同的結(jié)果
前一種忽略的顏色信息,而后一種總時返回false(因為參數(shù)類型不正確)

 public static void main(String[] args)
 {
  Point p = new Point(1,2);
  ColorPoint cp = new ColorPoint(1,2,Color.RED);
  System.out.printf(p.equals(cp)+"");//true
  System.out.printf(cp.equals(p)+"");//false

 }

可以嘗試以ColorPoint.equals在進(jìn)行“混合顏色比較時”忽略顏色信息
但這樣做確實提供了對稱性,但卻犧牲了傳遞性。
那該怎么解決???

事實上,這是面向?qū)ο笳Z言中關(guān)于等價關(guān)系的一個基本問題。
我們無法在擴展可實例化的類的同時,既增加新的組件,同時又保留equals約定
雖然沒有一種令人滿意的辦法既可以擴展可實例化的類,又增加組件,但還有一種不錯的方法。復(fù)合優(yōu)先于繼承

我們不再讓ColorPoint繼承Point,
而是在ColorPoint類中添加一個私有的Point域
以及一個公有的視圖(view)方法
此(view)方法返回一個與該色點處在相同位置的普通Point對象。

public class ColorPoint{
 private final Color color;
 private final Point point;
 public ColorPoint(int x,int y,Color color)
 {
  point = new Point(x,y);
  this.color=color;
 }
 /*view*/
 public Point asPoint()
 {
  return point;
 }
 
 @Override
 public boolean equals(Object o)
 {
  if(o instanceof ColorPoint)
  {
   ColorPoint cp =(ColorPoint)o;
   return this.point.equals(cp.point)&&
   this.color.equals(cp.color);//調(diào)用Point以及Color類的equals方法
  }
  //那么有色點與無色點會被判斷為不相同而返回false
  return false;
 }
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

分享標(biāo)題:淺談java重寫equals方法的種種坑
文章網(wǎng)址:http://aaarwkj.com/article44/iijphe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、網(wǎng)站內(nèi)鏈、定制網(wǎng)站、自適應(yīng)網(wǎng)站、商城網(wǎng)站、品牌網(wǎng)站設(shè)計

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)
国产成人拍国产亚洲精品| 国产在线麻豆在拍91精品| 国产亚洲精品免费专线视频| 人妻免费精品久久一区| 亚洲av男人电影天堂| 欧美日本一道本一区二区三区| 国产精品一二三在线看| 在线免费观看成人午夜福利| 国产 亚洲 一区 二区| 伊人久久亚洲福利精品| 91九色午夜在线观看| 97碰碰视频在线观看| 一区二区三区乱码av| 五月婷婷六月丁香免费视频| 国产老熟女一区二区三区| 欧美夫妻香蕉视频网站| 久久精品亚洲熟女av蜜謦| 午夜在线观看欧美福利| 另类视频在线观看免费| 欧美一级黄色免费电影| 日本精品在线小视频| 精品亚洲午夜久久久久| 久久五十路初次拍五十路| 国产亚洲精品第一综合| 亚洲精品成人一区二区| 色婷婷综合激情一区二区| 久久蜜臀av一区三区| 久久精品91久久久| 日韩一区二区人妻在线| 偷拍一区二区三区四区| 日韩精品色av一区二区| 日韩av不卡免费播放| 国产精品传媒免费在线观看| 男人的天堂在线观看黄片| 亚洲国产日本一区自拍| 国产夫妻一区二区三区| 91免费版在线观看网址| 美女在线观看av少妇| 中文有码人妻字幕在线| 好吊视频在线免费观看| 久久精品国产一区二区三|