阿里巴巴java規(guī)范手冊摘要

記錄一些自己不太熟悉的規(guī)范!

(一) 命名風格

  1. 【強制】POJO類中布爾類型的變量不要加is
    錯誤:Boolean isDeleted钓辆;正確:Boolean deleted
    原因:方法isDeleted()祖搓,部分框架反向解析戳葵,“以為”屬性是deleted,屬性獲取不到坝茎,拋出異常。

  2. 【推薦】將設(shè)計模式體現(xiàn)在名字中暇番,利于閱讀者快速理解架構(gòu)設(shè)計嗤放。
    正例:public class OrderFactory;
    public class LoginProxy;
    public class ResourceObserver;

  3. 【推薦】接口類的方法和屬性不加任何修飾符號(public 也不要加),保持代碼的簡潔性壁酬,并加上有效的Javadoc注釋次酌。盡量不要在接口里定義變量,如果一定要定義變量舆乔,肯定是與接口方法相關(guān)和措,并且是整個應(yīng)用的基礎(chǔ)常量。
    正例:接口方法簽名:void f(); 接口基礎(chǔ)常量表示:String COMPANY = "alibaba";
    反例:接口方法定義:public abstract void f();
    說明:JDK8中接口允許有默認實現(xiàn)蜕煌,那么這個default方法派阱,是對所有實現(xiàn)類都有價值的默認實現(xiàn)。

  4. 接口和實現(xiàn)類的命名有兩套規(guī)則
    : 1)【強制】對于Service和DAO類斜纪,基于SOA的理念贫母,暴露出來的服務(wù)一定是接口,內(nèi)部的實現(xiàn)類用Impl的后綴與接口區(qū)別盒刚。
    正例:CacheServiceImpl實現(xiàn)CacheService接口腺劣。
    2) 【推薦】 如果是形容能力的接口名稱,取對應(yīng)的形容詞做接口名(通常是–able的形式)因块。
    正例:AbstractTranslator實現(xiàn) Translatable橘原。

  5. 【參考】各層命名規(guī)約:
    A) Service/DAO層方法命名規(guī)約
    1) 獲取單個對象的方法用get做前綴。
    2) 獲取多個對象的方法用list做前綴涡上。
    3) 獲取統(tǒng)計值的方法用count做前綴趾断。
    4) 插入的方法用save/insert做前綴。
    5) 刪除的方法用remove/delete做前綴吩愧。
    6) 修改的方法用update做前綴芋酌。
    B) 領(lǐng)域模型命名規(guī)約
    1) 數(shù)據(jù)對象:xxxDO,xxx即為數(shù)據(jù)表名雁佳。
    2) 數(shù)據(jù)傳輸對象:xxxDTO脐帝,xxx為業(yè)務(wù)領(lǐng)域相關(guān)的名稱同云。
    3) 展示對象:xxxVO,xxx一般為網(wǎng)頁名稱堵腹。
    4) POJO是DO/DTO/BO/VO的統(tǒng)稱炸站,禁止命名成xxxPOJO。
    (二) 常量定義

  6. 【推薦】常量的復用層次有五層:跨應(yīng)用共享常量疚顷、應(yīng)用內(nèi)共享常量旱易、子工程內(nèi)共享常量、包內(nèi)共享常量荡含、類內(nèi)共享常量。
    1) 跨應(yīng)用共享常量:放置在二方庫中届垫,通常是client.jar中的constant目錄下释液。
    2) 應(yīng)用內(nèi)共享常量:放置在一方庫中,通常是modules中的constant目錄下装处。
    反例:易懂變量也要統(tǒng)一定義成應(yīng)用內(nèi)共享常量误债,兩位攻城師在兩個類中分別定義了表示“是”的變量:
    類A中:public static final String YES = "yes";
    類B中:public static final String YES = "y";
    A.YES.equals(B.YES),預(yù)期是true妄迁,但實際返回為false寝蹈,導致線上問題。
    3) 子工程內(nèi)部共享常量:即在當前子工程的constant目錄下登淘。
    4) 包內(nèi)共享常量:即在當前包下單獨的constant目錄下箫老。
    5) 類內(nèi)共享常量:直接在類內(nèi)部private static final定義。

(四) OOP規(guī)約

  1. 【強制】相同參數(shù)類型黔州,相同業(yè)務(wù)含義耍鬓,才可以使用Java的可變參數(shù),避免使用Object流妻。
    說明:可變參數(shù)必須放置在參數(shù)列表的最后牲蜀。
    (提倡同學們盡量不用可變參數(shù)編程) 正例:public User getUsers(String type, Integer... ids) {...}

  2. 【強制】Object的equals方法容易拋空指針異常,應(yīng)使用常量或確定有值的對象來調(diào)用equals绅这。
    正例:"test".equals(object);
    反例:object.equals("test");
    說明:推薦使用java.util.Objects#equals(JDK7引入的工具類)

  3. 關(guān)于基本數(shù)據(jù)類型與包裝數(shù)據(jù)類型的使用標準如下:
    1) 【強制】所有的POJO類屬性必須使用包裝數(shù)據(jù)類型涣达。
    2) 【強制】RPC方法的返回值和參數(shù)必須使用包裝數(shù)據(jù)類型。
    3) 【推薦】所有的局部變量使用基本數(shù)據(jù)類型证薇。
    說明:POJO類屬性沒有初值是提醒使用者在需要使用時度苔,必須自己顯式地進行賦值,任何NPE問題浑度,或者入庫檢查林螃,都由使用者來保證。
    正例:數(shù)據(jù)庫的查詢結(jié)果可能是null俺泣,因為自動拆箱疗认,用基本數(shù)據(jù)類型接收有NPE風險完残。
    反例:比如顯示成交總額漲跌情況,即正負x%横漏,x為基本數(shù)據(jù)類型谨设,調(diào)用的RPC服務(wù),調(diào)用不成功時缎浇,返回的是默認值扎拣,頁面顯示為0%,
    這是不合理的素跺,應(yīng)該顯示成中劃線二蓝。所以包裝數(shù)據(jù)類型的null值,能夠表示額外的信息指厌,如:遠程調(diào)用失敗刊愚,異常退出。

  4. 【強制】POJO類必須寫toString方法踩验。使用IDE的中工具:source> generate toString時鸥诽,如果繼承了另一個POJO類,注意在前面加一下super.toString箕憾。
    說明:在方法執(zhí)行拋出異常時牡借,可以直接調(diào)用POJO的toString()方法打印其屬性值,便于排查問題袭异。

  5. 【推薦】使用索引訪問用String的split方法得到的數(shù)組時钠龙,需做最后一個分隔符后有無內(nèi)容的檢查,否則會有拋IndexOutOfBoundsException的風險御铃。
    說明:
    String str = "a,b,c,,";
    String[] ary = str.split(",");
    // 預(yù)期大于3俊鱼,結(jié)果是3
    System.out.println(ary.length);

  6. 【推薦】類成員與方法訪問控制從嚴:
    2) 工具類不允許有public或default構(gòu)造方法。 ( 直接類名調(diào)用靜態(tài)方法畅买,不需要構(gòu)造器實例化 )

(五) 集合處理

  1. 【強制】 ArrayList的subList結(jié)果不可強轉(zhuǎn)成ArrayList并闲,否則會拋出ClassCastException異常,
    說明:subList 返回的是 ArrayList 的內(nèi)部類 SubList谷羞,并不是 ArrayList 帝火,
    而是 ArrayList 的一個視圖,對于SubList子列表的所有操作最終會反映到原列表上湃缎。

  2. 【強制】在subList場景中犀填,高度注意對原集合元素個數(shù)的修改,
    會導致子列表的遍歷嗓违、增加九巡、刪除均會產(chǎn)生ConcurrentModificationException 異常。

  3. 【強制】使用工具類Arrays.asList()把數(shù)組轉(zhuǎn)換成集合時蹂季,不能使用其修改集合相關(guān)的方法冕广,
    它的add/remove/clear方法會拋出UnsupportedOperationException異常疏日。
    說明:asList的返回對象是一個Arrays內(nèi)部類,并沒有實現(xiàn)集合的修改方法撒汉。
    Arrays.asList體現(xiàn)的是適配器模式沟优,只是轉(zhuǎn)換接口,后臺的數(shù)據(jù)仍是數(shù)組睬辐。
    String[] str = new String[] { "you", "wu" }; List list = Arrays.asList(str);
    第一種情況:list.add("yangguanbao"); 運行時異常挠阁。
    第二種情況:str[0] = "gujin"; 那么list.get(0)也會隨之修改。
    如果想修改:
    List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3));

  4. 【強制】泛型通配符<? extends T>來接收返回的數(shù)據(jù)溯饵,此寫法的泛型集合不能使用add方法侵俗,
    而<? super T>不能使用get方法,做為接口調(diào)用賦值時易出錯丰刊。
    說明:擴展說一下PECS(Producer Extends Consumer Super)原則:
    第一隘谣、頻繁往外讀取內(nèi)容的,適合用<? extends T>藻三。
    第二统捶、經(jīng)常往里插入的乾蓬,適合用<? super T>葛作。

  5. 【推薦】集合初始化時烦感,指定集合初始值大小帽芽。
    正例:initialCapacity =(需要存儲的元素個數(shù) / 負載因子) + 1稿茉。
    注意負載因子(即loader factor)默認為0.75颅夺,如果暫時無法確定初始值大小箕宙,請設(shè)置為16(即默認值)忘衍。
    反例:HashMap需要放置1024個元素逾苫,由于沒有設(shè)置容量初始大小,隨著元素不斷增加枚钓,容量7次被迫擴大铅搓,resize需要重建hash表,嚴重影響性能搀捷。

  6. 【推薦】使用entrySet遍歷Map類集合KV星掰,而不是keySet方式進行遍歷。(兩者都都要遍歷的時候)
    說明:keySet其實是遍歷了2次嫩舟,一次是轉(zhuǎn)為Iterator對象氢烘,另一次是從hashMap中取出key所對應(yīng)的value。
    而entrySet只是遍歷了一次就把key和value都放到了entry中家厌,效率更高播玖。如果是JDK8,使用Map.foreach方法饭于。 items.forEach((k,v)->{ System.out.println("Item : " + k + " Count : " + v); });
    正例:values()返回的是V值集合蜀踏,是一個list集合對象维蒙;keySet()返回的是K值集合,是一個Set集合對象脓斩;entrySet()返回的是K-V值組合集合木西。

  7. 【推薦】高度注意Map類集合K/V能不能存儲null值的情況,如下表格:
    集合類 Key Value Super 說明
    Hashtable 不允許為null 不允許為null Dictionary 線程安全
    ConcurrentHashMap 不允許為null 不允許為null AbstractMap 鎖分段技術(shù)(JDK8:CAS)
    TreeMap 不允許為null 允許為null AbstractMap 線程不安全
    HashMap 允許為null 允許為null AbstractMap 線程不安全

(六) 并發(fā)處理

  1. 【強制】線程池不允許使用Executors去創(chuàng)建随静,而是通過ThreadPoolExecutor的方式八千,這樣的處理方式讓寫的同學更加明確線程池的運行規(guī)則,規(guī)避資源耗盡的風險燎猛。說明:Executors返回的線程池對象的弊端如下:
    1)FixedThreadPool和SingleThreadPool:允許的請求隊列長度為Integer.MAX_VALUE恋捆,可能會堆積大量的請求,從而導致OOM重绷。
    2)CachedThreadPool和ScheduledThreadPool:允許的創(chuàng)建線程數(shù)量為Integer.MAX_VALUE沸停,可能會創(chuàng)建大量的線程,從而導致OOM昭卓。

  2. 【強制】SimpleDateFormat 是線程不安全的類愤钾,一般不要定義為static變量,如果定義為static候醒,必須加鎖能颁,或者使用DateUtils工具類。 正例:注意線程安全倒淫,使用DateUtils伙菊。亦推薦如下處理:
    private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
    @Override
    protected DateFormat initialValue() {
    return new SimpleDateFormat("yyyy-MM-dd");
    }
    };
    說明:如果是JDK8的應(yīng)用,可以使用Instant代替Date敌土,LocalDateTime代替Calendar镜硕,DateTimeFormatter代替SimpleDateFormat,官方給出的解釋:simple beautiful strong immutable thread-safe返干。

  3. 【強制】對多個資源兴枯、數(shù)據(jù)庫表、對象同時加鎖時矩欠,需要保持一致的加鎖順序财剖,否則可能會造成死鎖。 說明:線程一需要對表A晚顷、B峰伙、C依次全部加鎖后才可以進行更新操作,那么線程二的加鎖順序也必須是A该默、B瞳氓、C,否則可能出現(xiàn)死鎖。

  4. 【強制】并發(fā)修改同一記錄時匣摘,避免更新丟失店诗,需要加鎖。要么在應(yīng)用層加鎖音榜,要么在緩存加鎖庞瘸,要么在數(shù)據(jù)庫層使用樂觀鎖,使用version作為更新依據(jù)赠叼。 說明:如果每次訪問沖突概率小于20%擦囊,推薦使用樂觀鎖,否則使用悲觀鎖嘴办。樂觀鎖的重試次數(shù)不得小于3次瞬场。

  5. 【推薦】使用CountDownLatch進行異步轉(zhuǎn)同步操作,每個線程退出前必須調(diào)用countDown方法涧郊,線程執(zhí)行代碼注意catch異常贯被,確保countDown方法被執(zhí)行到,避免主線程無法執(zhí)行至await方法妆艘,直到超時才返回結(jié)果彤灶。 說明:注意,子線程拋出異常堆棧批旺,不能在主線程try-catch到幌陕。

  6. 【參考】volatile解決多線程內(nèi)存不可見問題。對于一寫多讀朱沃,是可以解決變量同步問題苞轿,但是如果多寫茅诱,同樣無法解決線程安全問題逗物。
    如果是count++操作,使用如下類實現(xiàn):AtomicInteger count = new AtomicInteger(); count.addAndGet(1);
    如果是JDK8瑟俭,推薦使用LongAdder對象翎卓,比AtomicLong性能更好(減少樂觀鎖的重試次數(shù))。

  7. 【參考】 HashMap在容量不夠進行resize時由于高并發(fā)可能出現(xiàn)死鏈摆寄,導致CPU飆升失暴,
    在開發(fā)過程中可以使用其它數(shù)據(jù)結(jié)構(gòu)或加鎖來規(guī)避此風險。

  8. 【參考】ThreadLocal無法解決共享對象的更新問題微饥,ThreadLocal對象建議使用static修飾逗扒。
    這個變量是針對一個線程內(nèi)所有操作共享的,所以設(shè)置為靜態(tài)變量欠橘,所有此類實例共享此靜態(tài)變量 矩肩,
    也就是說在類第一次被使用時裝載,只分配一塊存儲空間肃续,所有此類的對象(只要是這個線程內(nèi)定義的)都可以操控這個變量
    好處: ThreadLocal來消除共享對象的同步問題

(七) 控制語句

  1. 【推薦】表達異常的分支時黍檩,少用if-else方式叉袍,這種方式可以改寫成:
    if (condition) {
    ...
    return obj;
    }
    // 接著寫else的業(yè)務(wù)邏輯代碼;
    說明:如果非得使用if()...else if()...else...方式表達邏輯,【強制】避免后續(xù)代碼維護困難刽酱,請勿超過3層喳逛。
    正例:超過3層的 if-else 的邏輯判斷代碼可以使用衛(wèi)語句(將復雜的判斷拆分為多個)、策略模式棵里、狀態(tài)模式等來實現(xiàn)

  2. 【推薦】除常用方法(如getXxx/isXxx)等外润文,不要在條件判斷中執(zhí)行其它復雜的語句,將復雜邏輯判斷的結(jié)果賦值給一個有意義的布爾變量名殿怜,以提高可讀性转唉。 說明:很多if語句內(nèi)的邏輯相當復雜,閱讀者需要分析條件表達式的最終結(jié)果稳捆,才能明確什么樣的條件執(zhí)行什么樣的語句赠法,那么,如果閱讀者分析邏輯表達式錯誤呢乔夯? 正例:
    // 偽代碼如下
    final boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
    if (existed) {
    ...
    }

  3. 【參考】下列情形砖织,需要進行參數(shù)校驗:
    1) 調(diào)用頻次低的方法。
    2) 執(zhí)行時間開銷很大的方法末荐。此情形中侧纯,參數(shù)校驗時間幾乎可以忽略不計,但如果因為參數(shù)錯誤導致中間執(zhí)行回退甲脏,或者錯誤眶熬,那得不償失。
    3) 需要極高穩(wěn)定性和可用性的方法块请。
    4) 對外提供的開放接口娜氏,不管是RPC/API/HTTP接口。
    5) 敏感權(quán)限入口墩新。

  4. 【參考】下列情形贸弥,不需要進行參數(shù)校驗:
    1) 極有可能被循環(huán)調(diào)用的方法。但在方法說明里必須注明外部參數(shù)檢查要求海渊。
    2) 底層調(diào)用頻度比較高的方法绵疲。畢竟是像純凈水過濾的最后一道,參數(shù)錯誤不太可能到底層才會暴露問題臣疑。一般DAO層與Service層都在同一個應(yīng)用中盔憨,部署在同一臺服務(wù)器中,所以DAO的參數(shù)校驗讯沈,可以省略郁岩。
    3) 被聲明成private只會被自己代碼所調(diào)用的方法,如果能夠確定調(diào)用方法的代碼傳入?yún)?shù)已經(jīng)做過檢查或者肯定不會有問題,此時可以不校驗參數(shù)驯用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末脸秽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蝴乔,更是在濱河造成了極大的恐慌记餐,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件薇正,死亡現(xiàn)場離奇詭異片酝,居然都是意外死亡,警方通過查閱死者的電腦和手機挖腰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門雕沿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人猴仑,你說我怎么就攤上這事审轮。” “怎么了辽俗?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵疾渣,是天一觀的道長。 經(jīng)常有香客問我崖飘,道長榴捡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任朱浴,我火速辦了婚禮吊圾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘翰蠢。我一直安慰自己项乒,他們只是感情好,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布躏筏。 她就那樣靜靜地躺著板丽,像睡著了一般呈枉。 火紅的嫁衣襯著肌膚如雪趁尼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天猖辫,我揣著相機與錄音酥泞,去河邊找鬼。 笑死啃憎,一個胖子當著我的面吹牛芝囤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼悯姊,長吁一口氣:“原來是場噩夢啊……” “哼羡藐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悯许,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤仆嗦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后先壕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘩扼,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年垃僚,在試婚紗的時候發(fā)現(xiàn)自己被綠了集绰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡谆棺,死狀恐怖栽燕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情改淑,我是刑警寧澤纫谅,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站溅固,受9級特大地震影響付秕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜侍郭,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一询吴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧亮元,春花似錦猛计、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至煮甥,卻和暖如春盗温,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背成肘。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工卖局, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人双霍。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓砚偶,卻偏偏與公主長得像批销,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子染坯,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

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