阿里Java開發(fā)手冊(cè)思考(一)

題圖:by pixel2013 From pixabay

舊時(shí)王謝堂前燕户誓,
飛入尋常百姓家嫁赏。
小編將帶你們一起分析阿里巴巴Java開發(fā)手冊(cè)磨隘!

背景

阿里巴巴Java開發(fā)手冊(cè)是阿里巴巴集團(tuán)技術(shù)團(tuán)隊(duì)的集體智慧結(jié)晶和經(jīng)驗(yàn)總結(jié),以Java開發(fā)者為中心視角蹋订,劃分為編程規(guī)約率挣、異常日志、單元測(cè)試露戒、安全規(guī)約椒功、工程結(jié)構(gòu)、MySQL數(shù)據(jù)庫(kù)六個(gè)維度智什。手冊(cè)的愿景是碼出高效动漾、碼出質(zhì)量、效率優(yōu)先荠锭、質(zhì)量為本旱眯。

目的

之所以要寫這個(gè)系列的文章,首先是學(xué)習(xí)與總結(jié)证九,其次是思考與理解删豺,更是分享與交流,手冊(cè)中的每一條每一項(xiàng)都有其背后隱藏的原理與經(jīng)驗(yàn)愧怜,我們看到的只是冰山一角呀页,深入挖掘其背后的知識(shí)有益于更深刻的理解,并在自己實(shí)際編程中提高自己的基本技術(shù)素養(yǎng)拥坛。

主題

  • 【推薦】表達(dá)異常的分支時(shí)蓬蝶,少用 if-else 方式尘分,這種方式可以改寫成:
if (condition) { 
    ...
    return obj; 
}
// 接著寫 else 的業(yè)務(wù)邏輯代碼;

說(shuō)明:如果非得使用 if()...else if()...else...方式表達(dá)邏輯,【強(qiáng)制】避免后續(xù)代碼維
護(hù)困難丸氛,請(qǐng)勿超過(guò) 3 層培愁。
正例:超過(guò) 3 層的 if-else 的邏輯判斷代碼可以使用衛(wèi)語(yǔ)句、策略模式缓窜、狀態(tài)模式等來(lái)實(shí)現(xiàn)定续, 其中衛(wèi)語(yǔ)句示例如下:

public void today() { 
    if (isBusy()) {
        System.out.println(“change time.”); return;
    }
    if (isFree()) {
        System.out.println(“go to travel.”);
        return; 
    }
    System.out.println(“stay at home to learn Alibaba Java Coding Guidelines.”);
    return; 
}

我們?cè)噲D通過(guò)例子來(lái)分析下上面的規(guī)則,在分析之前雹洗,我們先明確在Java里香罐,默認(rèn)的equals和hashCode方法的實(shí)現(xiàn)卧波,以及把一個(gè)元素放入散列集合(HashSet时肿、HashMap等)時(shí),散列集合對(duì)equals和hashCode方法的判定規(guī)則港粱。
Java對(duì)象中默認(rèn)的equals(Object obj)方法用來(lái)判斷兩個(gè)對(duì)象是否“相同”螃成,如果“相同”則返回true,否則返回false查坪。hashCode()方法返回一個(gè)int數(shù)寸宏,這個(gè)整數(shù)值是將該對(duì)象的內(nèi)部地址轉(zhuǎn)換成一個(gè)整數(shù)返回的 。
在散列集合中存儲(chǔ)一個(gè)對(duì)象時(shí)偿曙,先進(jìn)行hashCode的比較氮凝,如果hashCode不想等,則直接放入望忆,否則繼續(xù)進(jìn)行equals的比較罩阵,equals不相等才放入,equals不相等就直接丟棄了启摄。

理解

  • 如果只重寫equals而不重寫hashCode會(huì)導(dǎo)致什么問(wèn)題稿壁?
package com.test;
import java.util.HashSet;
import java.util.Set;
public class OverrideEqualsTest {    
    public static void main(String[] args) {
        Set<Point> set = new HashSet<Point>();
        Point p1 = new Point(1, 1);
        Point p2 = new Point(1, 1);
        System.out.println("p1.equals(p2):" + p1.equals(p2));
        set.add(p1);
        set.add(p2);
        set.add(p1);
        System.out.println("set.size():" + set.size());        
        for (Point p : set) {
            System.out.println(p);
        }
    }    
    static class Point {        
        private int x;        
        private int y;        
        public Point(int x, int y) {            
            super();            
            this.x = x;            
            this.y = y;
        }        
        @Override
        public boolean equals(Object obj) {            
            if (this == obj) {              
                return true;  
            }          
            if (obj == null) {                
                return false; 
            }           
            if (getClass() != obj.getClass()) {                
                return false;
            }
            Point other = (Point) obj;            
            if (x != other.x) {                
                return false;  
            }          
            if (y != other.y) {               
                return false;  
            }          
            return true;
        }        
        @Override
        public String toString() {            
            return "Point [x=" + x + ", y=" + y + "]";
        }
    }
}

運(yùn)行結(jié)果:
p1.equals(p2):true
set.size():2
Point[x=1,y=1]
Point[x=1,y=1]

分析:由于沒有重寫hashCode方法,p1和p2對(duì)象默認(rèn)的hashCode方法返回的兩個(gè)對(duì)象地址轉(zhuǎn)換的整數(shù)肯定不同歉备,所以p1和p2都可以放入set中傅是,所以這并不是我們期望的結(jié)果。

  • ?如果只重寫hashCode而不重寫equals又會(huì)導(dǎo)致什么問(wèn)題蕾羊?
package com.test;
import java.util.HashSet;
import java.util.Set;
public class OverrideHashCodeTest {    
    public static void main(String[] args) {
        Set<Point> set = new HashSet<Point>();
        Point p1 = new Point(1, 1);
        Point p2 = new Point(1, 1);
        System.out.println("p1.equals(p2):" + p1.equals(p2));
        set.add(p1);
        set.add(p2);
        set.add(p1);
        System.out.println("set.size():" + set.size());        
        for (Point p : set) {
            System.out.println(p);
        }
    }    
    static class Point {        
        private int x;        
        private int y;        
        public Point(int x, int y) {            
            super();            
            this.x = x;            
            this.y = y;
        }        
        @Override
        public int hashCode() {            
            final int prime = 3L;            
            int result = 1;
            result = prime * result + x;
            result = prime * result + y;            
            return result;
        }        
        @Override
        public String toString() {            
            return "Point [x=" + x + ", y=" + y + "]";
        }
    }
}

運(yùn)行結(jié)果:
p1.equals(p2):false
set.size():2
Point[x=1,y=1]
Point[x=1,y=1]

分析:由于沒有重寫equals方法喧笔,p1和p2對(duì)象的默認(rèn)的equals方法通過(guò)“==”來(lái)比較,而p1和p2是兩個(gè)不同的對(duì)象龟再,所以p1和p2都可以放入set中书闸,所以這也不是我們期望的結(jié)果。
所以綜上吸申,當(dāng)我們同時(shí)重寫equals和hashCode方法后梗劫,才能在散列集合操作中得到一致性的結(jié)果享甸。

  • 對(duì)象放入散列集合后,又修改了影響hashCode的值梳侨,后果蛉威?
package com.test;
public class Test {    
    public static void main(String[] args) {
        Point p1 = new Point(1, 1);
        Point p2 = new Point(2, 2);
        set.add(p1);
        set.add(p2);
        System.out.println("set.size():" + set.size());
        p2.setY(3);
        set.remove(p1);
        set.remove(p2);
        System.out.println("set.size():" + set.size());
    }
}

運(yùn)行結(jié)果:
set.size():2
set.size():1

分析:由于在執(zhí)行期間,修改了p2對(duì)象的y值走哺,導(dǎo)致p2對(duì)象的hashCode返回值有變化蚯嫌,所以hashset的remove方法將找不到新的hashCode所映射的對(duì)象,導(dǎo)致內(nèi)存泄漏丙躏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末择示,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子晒旅,更是在濱河造成了極大的恐慌栅盲,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件废恋,死亡現(xiàn)場(chǎng)離奇詭異谈秫,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)鱼鼓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門拟烫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人迄本,你說(shuō)我怎么就攤上這事硕淑。” “怎么了嘉赎?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵置媳,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我曹阔,道長(zhǎng)半开,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任赃份,我火速辦了婚禮寂拆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘抓韩。我一直安慰自己纠永,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布谒拴。 她就那樣靜靜地躺著尝江,像睡著了一般。 火紅的嫁衣襯著肌膚如雪英上。 梳的紋絲不亂的頭發(fā)上炭序,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天啤覆,我揣著相機(jī)與錄音,去河邊找鬼惭聂。 笑死窗声,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辜纲。 我是一名探鬼主播笨觅,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼耕腾!你這毒婦竟也來(lái)了见剩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤扫俺,失蹤者是張志新(化名)和其女友劉穎苍苞,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牵舵,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柒啤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了畸颅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡方援,死狀恐怖没炒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情犯戏,我是刑警寧澤送火,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站先匪,受9級(jí)特大地震影響种吸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜呀非,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一坚俗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧岸裙,春花似錦猖败、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至剧董,卻和暖如春幢尚,著一層夾襖步出監(jiān)牢的瞬間破停,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工尉剩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辱挥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓边涕,卻偏偏與公主長(zhǎng)得像晤碘,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子功蜓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

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