麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

java中的equals+hashCode

2019-11-14 15:14:28
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

【0】README

0.1)本文轉(zhuǎn)自 core java volume 1, 旨在理清 equals + hashCode方法;


【1】equals方法

1.1) Object中的 equals 方法用于檢測(cè)一個(gè)對(duì)象是否等于另外一個(gè)對(duì)象;(在Object類中, 這個(gè)方法比較的是內(nèi)存地址, 判斷的是兩個(gè)對(duì)象是否具有相同引用)
1.2)看個(gè)荔枝:
這里寫(xiě)圖片描述
Hint)

  • H1)為了防備name 或 hireDay 可能為null的情況: 需要使用 Objects.equals 方法;如果兩個(gè)參數(shù)都為 null, Objects.equals(a, b) 返回 true; 如果其中一個(gè)為null, 則返回 false; 否則,兩個(gè)參數(shù)都不為null, 則調(diào)用 a.equals(b);(注意是Objects not Object)
  • H2)利用這個(gè)方法, Employee.equals 方法的最后一條語(yǔ)句要改寫(xiě)為:
return Objects.equals(name, other.name)         && salary == other.salary         && Objects.equals(hireDay, other.hireDay);

1.3)在子類中定義 equals 方法時(shí), 首先調(diào)用超類的 equals; 如果檢測(cè)失敗,對(duì)象就不可能相等, 如果超類中的域都相等, 就需要比較子類中的實(shí)例域;
這里寫(xiě)圖片描述
1.4)java語(yǔ)言規(guī)范要求 equals 具有以下特性:

  • 自反性:非空引用 x,x.equals(x) 應(yīng)該返回true;
  • 對(duì)稱性:非空引用x 和 y, x.equals(y) 返回ture, 那么 y.equals(x) 也應(yīng)該返回ture;
  • 傳遞性:對(duì)于 非空引用x 、y 和 z, x.equals(y) 返回ture, 那么 y.equals(z) 也應(yīng)該返回ture, 則 x.equals(z) 也應(yīng)該返回 true;
  • 一致性:如果x 和 y 引用的對(duì)象沒(méi)有發(fā)生變化, 反復(fù)調(diào)用 x.equals(y) 應(yīng)該返回同樣的結(jié)果;
  • 對(duì)于任意非空應(yīng)用x, x.equals(null) 應(yīng)該返回false;

1.5)出現(xiàn)的問(wèn)題+解決方法

  • 當(dāng)子類和父類對(duì)象分別作為equals 的隱式參數(shù),導(dǎo)致不滿足對(duì)稱性的情況: e.equals(m), 這里的e是一個(gè) Employee對(duì)象,m是一個(gè) Manager對(duì)象,并且兩個(gè)對(duì)象具有相同的屬性值;如果在 Employee.equals中用 instanceof 檢測(cè),就會(huì)返回 true, 然而這意味著反過(guò)來(lái)調(diào)用:
    m.equals(e) 也需要返回true; 對(duì)稱性不允許這個(gè)方法調(diào)用返回 false, 或者拋出異常;猛然間,讓人感覺(jué)到 instanceof 并不是那么完美;
  • 下面從兩個(gè)截然不同的情況看一下這個(gè)問(wèn)題:
    • 1)如果子類能夠擁有自己的相等概念, 則對(duì)稱性需要將強(qiáng)制采用getClass 進(jìn)行檢測(cè);
    • 2)如果由超類決定相等的概念, 那么就可以使用 instanceof 進(jìn)行檢測(cè), 這樣可以在不同子類的對(duì)象間進(jìn)行相等的比較;

【2】下面給出編寫(xiě)一個(gè)完美的 equals 方法的建議:

  • 2.1)顯式參數(shù)命名為 otherObject, 稍后需要將它轉(zhuǎn)換為另一個(gè)叫做 other的變量;
  • 2.2)檢測(cè)this 與 otherObject 是否引用同一個(gè)對(duì)象:
    if(this == otherObject) return true; 實(shí)際上, 這是一種經(jīng)常采用的形式, 因?yàn)橛?jì)算這個(gè)等式要比一個(gè)一個(gè)地比較類中的域所付出的代價(jià)小得多;
  • 2.3)檢測(cè)otherObject 是否為 null, 如果為 null ,則返回 false, 這項(xiàng)檢測(cè)很有必要:
    if(otherObject == null) return false;
  • 2.4)比較this 與 otherObject 是否屬于同一個(gè)類: 如果equals 的語(yǔ)義在每個(gè)子類中有所改變,就是用 getClass 進(jìn)行檢測(cè):if(getClass() != otherObject.getClass()) return false;
  • 2.5) 將 otherObject 轉(zhuǎn)換為 相應(yīng)的類類型變量:
    ClassName other = (ClassName)otherObject;
  • 2.6)現(xiàn)在開(kāi)始對(duì)所有需要比較的域進(jìn)行比較了:
    使用 == 比較基本類型域, 使用 equals比較對(duì)象域, 如果所有的域都匹配返回 true, 否則返回 false;
    return field1 == other.field1 && Objects.equals(field2, other.field2) && ......;
    如果在子類中重新定義 equals, 就要在其中包含 調(diào)用 super.equals(other);

Hint)對(duì)于數(shù)組類型的域, 可以使用靜態(tài)的Arrays.equals 方法檢測(cè)相應(yīng)的 數(shù)組元素是否相等;
Alert)看個(gè)荔枝(下面是實(shí)現(xiàn) equals 方法的一種常見(jiàn)的錯(cuò)誤):
這里寫(xiě)圖片描述
代碼分析(Analysis):

  • A1)這個(gè)方法聲明的顯式參數(shù)類型是 Employee, 其結(jié)果并沒(méi)有 覆蓋 Object類的 equals 方法,而是定義了一個(gè)完全無(wú)關(guān)的方法;
  • A2)為了避免發(fā)生類型錯(cuò)誤, 可以使用 @Override 對(duì)覆蓋超類的方法進(jìn)行標(biāo)記;

    @Overridepublic boolean equals(Object other)
  • A3)如果出現(xiàn)了錯(cuò)誤,并且正在定義一個(gè)新方法,編譯器就會(huì)給出 錯(cuò)誤報(bào)告;如, 假設(shè)將下面的聲明添加到 Employee類中, 就會(huì)看到一個(gè)錯(cuò)誤報(bào)告, 這是因?yàn)檫@個(gè)方法并沒(méi)有覆蓋超類Object 中的 任何方法:

    @Override public boolean equals(Employee other)

    【3】hashCode 方法

    3.1)定義:散列碼是由對(duì)象導(dǎo)出的一個(gè)整型值, 散列碼沒(méi)有規(guī)律的;如,x和y 是兩個(gè)不同的對(duì)象, x.hashCode() 和 y.hashCode() 基本上不會(huì)相同的;
    3.2)String 類的 hashCode 散列碼:

  • 3.2.1)String類通過(guò)下列算法計(jì)算散列碼:

    int hash = 0;for(int i=0;i<length(); i++)hash = 31 * hash + charAt(i);
  • 3.2.2) hashCode方法定義在了 Object類, 因此每個(gè)對(duì)象都有一個(gè)默認(rèn)的散列碼, 其值為對(duì)象的存儲(chǔ)地址:
    這里寫(xiě)圖片描述
    對(duì)以上打印結(jié)果的分析(Analysis):

    • A1)字符串s 和 t 擁有相同的散列碼, 這是因?yàn)樽址纳⒘写a是由內(nèi)容導(dǎo)出的, 而字符串緩沖sb 和 tb 卻有著不同的散列碼,這是因?yàn)?在StringBuffer 類中沒(méi)有定義hashCode 方法,它的散列碼是有 Object類的默認(rèn) hashCode 方法,以便用戶可以 將對(duì)象插入到散列表中;
    • A2) hashCode方法應(yīng)該返回一個(gè)整型數(shù)值,并合理的組合實(shí)例域的散列碼, 以便能夠讓各個(gè)不同的對(duì)象產(chǎn)生的散列碼更加均勻;

3.3)看個(gè)荔枝, 下面是 Employee類 的 hashCode方法:
這里寫(xiě)圖片描述
3.4)還可以在java7中做兩個(gè)改進(jìn)(imPRovement):

  • I1) 最好使用 null 安全 的方法 Objects.hashCode , 如果參數(shù)為null, 這個(gè)方法會(huì)返回0, 否則返回對(duì)參數(shù)調(diào)用 hashCode的結(jié)果;
  • I2)還有一個(gè)方法: 需要組合多個(gè)散列值, 可以調(diào)用 Objects.hash 并提供多個(gè)參數(shù),這個(gè)方法會(huì)對(duì)各個(gè)參數(shù)調(diào)用 Objects.hashCode, 并組合這些散列值; 如 Employee.hashCode 的方法可以簡(jiǎn)寫(xiě)為:

    public int hashCode(){return Objects.hash(name, salary, hireDay);}

    Attention)

  • A1) equals 方法與 hashCode 的定義必須一致, 如果x.equals(y) 返回 true, 那么 x.hashCode() 就必須與 y.hashCode() 具有相同的值;
  • A2) 如, 如果用定義的Employee.equals 比較雇員的Id, 那么 hashCode就需要散列Id, 而不是 雇員的 姓名或存儲(chǔ)地址;

Hint)如果存在數(shù)組類型的域, 那么可以使用靜態(tài)的 Arrays.hashCode 方法計(jì)算一個(gè)散列碼, 這個(gè)散列碼由數(shù)組元素的散列碼組成;


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 国产精品高潮99久久久久久久 | av在线直播观看 | 中文字幕爱爱视频 | 黄色片网站在线播放 | 黄色av免费网站 | 黄色网欧美 | 亚洲热线99精品视频 | 久久成人免费观看 | 黄片毛片一级 | 高清国产免费 | 久久久www成人免费精品 | 欧美视频99| 亚洲精久久 | 福利四区| 国产精品久久久久久久久久大牛 | 欧日韩在线| 蜜桃av网 | 永久免费毛片 | 日韩视频在线观看免费视频 | 毛片在线播放视频 | 国产噜噜噜| h视频在线播放 | 钻石午夜影院 | 黄色片网站在线免费观看 | 香蕉久久久精品 | 久久亚洲线观看视频 | 国产精品自在线拍 | 日本s级毛片免费观看 | 99影视电影电视剧在线播放 | 狠狠操操 | 亚洲啪| 婷婷久久综合九色综合色多多蜜臀 | 91九色网址| 最新欧美精品一区二区三区 | 国语自产免费精品视频在 | 日本成人一二三区 | 国产女王女m视频vk 中文日韩 | 最新福利在线 | 亚洲一区二区三区四区精品 | 免费观看国产精品视频 | 娇喘视频在线观看 |