優(yōu)雅編程之這樣使用對(duì)象通用方法余指,你就“正巢度”了(三十四)

開(kāi)心一笑

【一對(duì)夫婦避孕失敗后生了一個(gè)小男孩,孩子一生出來(lái)就緊握拳頭酵镜,一直笑個(gè)不停.護(hù)士把他的拳頭一掰開(kāi).發(fā)現(xiàn)里面有一把避孕藥碉碉,接著小男孩開(kāi)口說(shuō)話了:“你們兩個(gè)想弄死我,沒(méi)那么容易淮韭,哈哈哈】

提出問(wèn)題

項(xiàng)目開(kāi)發(fā)中垢粮,對(duì)象都通用的方法要注意那些???

解決問(wèn)題

勵(lì)志圖片
覆蓋equals時(shí)請(qǐng)遵守通用約定

先溫習(xí)下枯燥的理論知識(shí),很無(wú)聊缸濒,但很重要足丢。

  • 自反性:對(duì)于任何非null的引用值x,x.equals(x)必須返回true.
  • 對(duì)稱性:對(duì)于非空的引用值x,y庇配,當(dāng)且僅當(dāng)x.equals(y)返回true時(shí)斩跌,y.equals(x)必須返回true.
  • 傳遞性:對(duì)于任何非null的引用值x,y,z,如果x.equals(y)=true捞慌,y.equals(z)=true耀鸦,那么x.equals(z)也必須返回true。
  • 一致性:對(duì)于任何非null的引用值x,y啸澡,只要equals的比較操作在對(duì)象中所用的信息沒(méi)有被修改袖订,多次調(diào)用x.equals(y)就會(huì)一致地返回true,或一致地返回false.
  • 對(duì)于非null的引用值x嗅虏,x.equals(null)必須返回false.

高質(zhì)量equals方法的訣竅

  1. 使用==操作符檢查參數(shù)是否為這個(gè)對(duì)象的引用洛姑。
  2. 使用instanceof操作符檢查參數(shù)是否為正確的類型。
  3. 把參數(shù)轉(zhuǎn)換成正確的類型皮服。
  4. 當(dāng)編寫(xiě)完成了equals方法之后楞艾,應(yīng)該問(wèn)自己三個(gè)問(wèn)題参咙,它是否是對(duì)稱的、傳遞的硫眯、一致的蕴侧。

我用開(kāi)發(fā)工具自動(dòng)幫我生成equals方法:

@Override
public boolean equals(Object o) {
    //使用==操作符檢查參數(shù)是否為這個(gè)對(duì)象的引用
    if (this == o) return true;
    //使用instanceof操作符檢查參數(shù)是否為正確的類型
    if (!(o instanceof AyTest)) return false;
    //把參數(shù)轉(zhuǎn)換成正確的類型
    AyTest ayTest = (AyTest) o;
    
    if (flowerNum != ayTest.flowerNum) return false;

    return true;
}
覆蓋equals時(shí)總要覆蓋hashCode

覆蓋equals方法,必須覆蓋hashCode方法两入。如果不這樣做净宵,就會(huì)違反Object.hashCode的通用約定,從而也導(dǎo)致該類無(wú)法結(jié)合所有基于散列的結(jié)合一塊正常運(yùn)轉(zhuǎn)裹纳,這樣的結(jié)合包括HashMap择葡、HashSet和Hashtable

//這里引用課本的例子,非原創(chuàng)
public final class PhoneNumber {  

    private final short areaCode;        
    private final short prefix;     
    private final short lineNumber;  
      
    public PhoneNumber(int areaCode, int prefix, int lineNumber) {  
        rangeCheck(areaCode, 999,  "area code");  
        rangeCheck(prefix, 999,  "prefix");  
        rangeCheck(lineNumber, 9999,  "line number");  
          
        this.areaCode = (short)areaCode;  
        this.prefix = (short)prefix;  
        this.lineNumber = (short)lineNumber;  
    }  
      
    private static void rangeCheck(int arg, int max, String name) {  
        if (arg < 0 || arg > max) {  
            throw new IllegalArgumentException(name + ": " + arg);  
        }  
    }  
      
    @Override  
    public boolean equals(Object o) {  
        if (o == this) {  
            return true;  
        }   
        if (!(o instanceof PhoneNumber)) {  
            return false;  
        }    
        PhoneNumber pNumber = (PhoneNumber)o;   
        return (pNumber.lineNumber == lineNumber) && (pNumber.prefix == prefix) && (pNumber.areaCode == areaCode);  
    }  
}  

測(cè)試?yán)樱?/p>

public static void hashCodePhoneNumber() {  
    Map<PhoneNumber, String> map = new HashMap<PhoneNumber, String>();  
    PhoneNumber phoneNumber = new PhoneNumber(707, 867, 9876);  
    map.put(phoneNumber, "Jenny");
    //這里是重點(diǎn) 重點(diǎn) 重點(diǎn)  一個(gè)是new 出來(lái)的 一個(gè)是 原來(lái)的phoneNumber    
    System.out.println(map.get(new PhoneNumber(707, 867, 9876)));  
    System.out.println(map.get(phoneNumber));  
} 

執(zhí)行結(jié)果:

null    
Jenny   

解釋一下:

不去覆蓋hashCode剃氧,使用map.put時(shí)刁岸,我們是把這些PhoneNumber對(duì)象放在各個(gè)不同的盒子里,而我們?nèi)ap.get()的時(shí)候她我,只是去某一個(gè)盒子里去找,而如果我們覆蓋了hashCode方法迫横,這時(shí)番舆,如果通過(guò)hashCode計(jì)算出來(lái)的值是相等的,就會(huì)放在同一個(gè)盒子里矾踱。這樣恨狈,只要我們對(duì)象中保存的值是完全一致的,就會(huì)找到這個(gè)key所對(duì)應(yīng)的value呛讲。

始終要覆蓋toString

如果我們不覆蓋類的toString()方法禾怠,后果可能是當(dāng)我們需要去打印這個(gè)類的對(duì)象時(shí),會(huì)有一些并非是我們想要的那種結(jié)果”锤椋現(xiàn)在開(kāi)發(fā)工具很方便吗氏,可以使用開(kāi)發(fā)工具自動(dòng)幫助我們生成。

謹(jǐn)慎的覆蓋clone

拷貝的含義是:

  • x.clone() != x
  • x.clone().getClass() == x.getClass()
  • x.clone().equals(x)

覆蓋clone方法要非常小心雷逆,如果類里面含有復(fù)雜數(shù)據(jù)類型弦讽,要進(jìn)行深度復(fù)制,如果類里面有final屬性膀哲,則無(wú)法進(jìn)行clone往产,因?yàn)閒inal屬性在clone時(shí)無(wú)法再進(jìn)行賦值。

最好呢就是別去覆蓋這個(gè)方法某宪,需要復(fù)制的話可以使用拷貝構(gòu)造器和靜態(tài)拷貝工廠

考慮實(shí)現(xiàn)Comparable接口
  • comparaTo方法不是Object中的方法仿村,而是Comparable接口中唯一的方法。該方法不僅可進(jìn)行等同性比較兴喂,還可以進(jìn)行順序比較蔼囊。

  • 接口的通用約定是按照equals方法來(lái)定義的焚志,但有序集合使用了compareTo方法的等同性測(cè)試。

  • 如果是是一個(gè)值類压真,而且具有明顯的內(nèi)在排序關(guān)系娩嚼,就因該堅(jiān)決實(shí)現(xiàn)該接口。

  • 如果你正在編寫(xiě)一個(gè)值類滴肿,它具有非常明顯的內(nèi)在排序關(guān)系岳悟,比如按字母順序、按數(shù)值順序或者按照年代順序泼差,那就應(yīng)該堅(jiān)決考慮實(shí)現(xiàn)這個(gè)接口贵少。

參考文章

【1】Effective Java:對(duì)于所有對(duì)象都通用的方法
【2】Java中equals和==的區(qū)別
【3】Effective Java——對(duì)所有對(duì)象通用的方法
【4】Effective Java 讀書(shū)筆記之二 對(duì)于所有對(duì)象都通用的方法
【5】考慮實(shí)現(xiàn)Comparable接口

讀書(shū)感悟

來(lái)自韓寒《我所理解的生活》

  • 我所理解的生活就是做著自己喜歡的事情,養(yǎng)活自己堆缘,養(yǎng)活家人滔灶。生活不是攀爬高山,也不是深潛海溝吼肥,它只是在一張標(biāo)配的床上睡出你的身形录平。我所理解的生活就是和自己喜歡的一切在一起。
  • 緣分不是走在街上非要撞見(jiàn)缀皱,緣分就是睡前醒后彼此想念斗这。
  • 打死也不能放棄,窮死也不能?chē)@氣啤斗,要讓笑話你的人成為笑話表箭。
  • 可以后悔,但不留遺憾钮莲,有很多事情做了以后發(fā)現(xiàn)自己傻了或者失敗了免钻,但還是要去做。
  • 世間萬(wàn)千種寵愛(ài)崔拥,無(wú)數(shù)種人心极舔,得之我幸,不得我也沒(méi)什么不幸握童。
  • 我相信真誠(chéng)相待姆怪,也相信倒霉認(rèn)栽。
  • 每個(gè)人的道路都不同澡绩,我走在我的野路上稽揭,她走在她的大路上,都值得祝福肥卡。只要不走歪路邪路溪掀,每條道路都有成功的方式。

其他

如果有帶給你一絲絲小快樂(lè)步鉴,就讓快樂(lè)繼續(xù)傳遞下去揪胃,歡迎轉(zhuǎn)載璃哟,點(diǎn)贊,頂喊递,歡迎留下寶貴的意見(jiàn)随闪,多謝支持!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末骚勘,一起剝皮案震驚了整個(gè)濱河市铐伴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俏讹,老刑警劉巖当宴,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異泽疆,居然都是意外死亡户矢,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)殉疼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)梯浪,“玉大人,你說(shuō)我怎么就攤上這事瓢娜∏ぃ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵恋腕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我逆瑞,道長(zhǎng)荠藤,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任获高,我火速辦了婚禮哈肖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘念秧。我一直安慰自己淤井,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布摊趾。 她就那樣靜靜地躺著币狠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪砾层。 梳的紋絲不亂的頭發(fā)上漩绵,一...
    開(kāi)封第一講書(shū)人閱讀 52,475評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音肛炮,去河邊找鬼止吐。 笑死宝踪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的碍扔。 我是一名探鬼主播瘩燥,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼不同!你這毒婦竟也來(lái)了厉膀?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤套鹅,失蹤者是張志新(化名)和其女友劉穎站蝠,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體卓鹿,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菱魔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吟孙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澜倦。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖杰妓,靈堂內(nèi)的尸體忽然破棺而出藻治,到底是詐尸還是另有隱情,我是刑警寧澤巷挥,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布桩卵,位于F島的核電站,受9級(jí)特大地震影響倍宾,放射性物質(zhì)發(fā)生泄漏雏节。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一高职、第九天 我趴在偏房一處隱蔽的房頂上張望钩乍。 院中可真熱鬧,春花似錦怔锌、人聲如沸寥粹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)涝涤。三九已至,卻和暖如春岛杀,著一層夾襖步出監(jiān)牢的瞬間妄痪,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工楞件, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衫生,地道東北人裳瘪。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像罪针,于是被迫代替她去往敵國(guó)和親彭羹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容