阿里巴巴JAVA開發手冊

開發手冊

1、編程規範

(一)命名規範

類型 規範
命名 不能以_$開頭或結尾,正確英文拼寫和語法,避免不規範縮寫
類名 UpperCamelCase風格(領域模式除外,DO、BO、DTO、VO)
方法 參數 變量名 lowerCamelCase風格
常量 全大寫,以_隔開,語義表達完整,不要嫌長
抽象類名 以Abstract或Base開頭
異常類名 以Exception結尾
測試類名 以Test結尾
常量類 以Consts結尾
數組 數組定義以下:String[] args
布爾變量 不能加is
包名 小寫,一個天然語義單詞,單數形式
設計模式 在類名中體現出具體模式
接口 字段和方法不加任何修飾符,以形容能力的接口名稱,取形容詞爲接口名(一般-able形式)
接口實現類 以Impl結尾
枚舉類 以Enum結尾,枚舉成員全大寫,以_隔開(枚舉就是特殊的常量類,且構造方法被默認強制私有)

各層命名規範java

Service/DAO層方法命名規範 1 獲取單個對象的方法用 get 作前綴
2 獲取多個對象的方法用 list 作前綴
3 獲取統計值的方法用 count 作前綴
4 插入的方法用 save(推薦)或 insert 作前綴
5 刪除的方法用 remove(推薦)或 delete 作前綴
6 修改的方法用 update 作前綴
領域模型命名規範 1 數據對象:xxxDO,xxx爲數據表名
2 數據傳輸對象:xxxDTO,xxx爲業務領域相關的名稱
3 展現對象:xxxVO,xxx通常爲網頁名稱
4 POJODO/DTO/BO/VO的統稱,禁止命名爲xxxPOJO

(二)常量定義

類型 規範
常量 不容許魔法值(未定義常量)直接出如今代碼中
長整型 初始化用L(大寫)結尾,避免l(小寫)與數字1混淆
常量類 按功能進行分類,分開維護
複用層次 1 跨應用共享常量
2 應用內共享常量
3 子工程內共享常量
4 包內共享常量
5 類內共享常量
Enum類 若是變量在範圍內變化用Enum,若是還帶有名稱以外的延伸屬性,必須用Enum類,如MONDAY(1)

(三)格式規約

類型 規範
大括號的使用 1 空代碼塊 簡潔地寫成{},不須要換行
2 非空代碼塊:左大括號前不換行,後換行;
右大括號前換行,後換行(還有else則不換行,表示終止必須換行)
括號的使用 左括號與後一個字符之間不出現空格,右括號與前一個字符之間也不能出現空格
關鍵字 if/for/while/switch/do 等保留字與左右括號之間都必須加空格
運算符 任何運算符左右都必須加一個空格
縮進 縮進採用4個空格,禁止使用tab字符
例: 圖片描述
單行字符 單行字符數限制不能超過120個,超出須要換行,遵循原則以下:
1 第二行相對第一行縮進4字符,第三行開始,相對第二行再也不縮進;
2 運算符與下文一塊兒換行
3 方法調用.符號與下文一塊兒換行
4 多個參數超行,逗號後進行換行
5 在括號前不要換行
方法參數 方法參數在定義和傳入時,多個參數逗號後邊必須加空格
編碼和換行符 IDE的text file encoding設置爲utf-8,IDE文件換行符使用Unix格式,而非windows格式
字符對齊 沒有必要增長若干空格來使某一行的字符與上一行的相對字符對齊
方法體 方法體內的執行語句組、變量的定義語句組、不一樣的業務邏輯之間或者不一樣的語義之間插入一個空行(沒有必要插入多行)。相同業務邏輯和語義之間bu須要插入空行

(四)OOP規約

類型 規範
靜態成員訪問 直接使用類名訪問,避免經過對象引用訪問,無謂增長編譯器解析成本。
覆寫方法 全部覆寫方法,必須添加@Override註解(準確判斷是否覆蓋成功)
可變參數編程 相同參數類型,相同業務含義,纔可以使用Java的可變參數,避免使用Object,可變參數必須放置在參數列表的最後
對外暴露的接口簽名 原則上不容許修改方法簽名,避免對接口調用方產生影響,接口過期必須添加@Deprecated註解,並清晰第說明採用的新接口或者新服務是什麼
過期的類或方法 不能調用過期的類或方法,做爲調用方,有義務去考證過期方法的新實現是什麼
equals方法 應使用常量或確保有值的對象來調用equals,避免空指針異常
包裝類比較 全部的相同類型的包裝類之間值的比較,所有使用equals方法比較,
緣由:Integer在-128 至127之間的賦值,Integer對象在IntegerCache.cache產生,會複用已有對象,而在這個區間以外,都會在堆上產生。
例子:Integer a = 111;Integer b = 111; a == b爲true;
Integer a = 1111;Integer b = 1111;a == b爲false
基本數據類型
包裝數據類型使用標準
1 全部的POJO類屬性必須使用包裝數據類型
2 RPC方法的返回值和參數必須使用包裝數據類型
3全部的局部變量【推薦】使用基本數據類型。
說明:POJO類無初值提醒使用者顯式賦值,任何NPE問題,入庫檢查,都由使用者保證。
POJO類 定義DO/DTO/VO等POJO類時,不要設定任何屬性默認值
serialVersionUID 序列化類新增屬性時,請不要修改serialVersionUID字段,避免反序列化失敗;
若是徹底不兼容升級,避免反序列化混亂,那麼請修改serialVersionUID值
構造方法 構造方法裏面禁止寫入任何業務邏輯,若是有初始化邏輯,請放在init方法中
toString方法 POJO類必須寫toString方法,使用IDE中的工具,source>generate toString時,若是繼承了另外一個POJO類,注意在前面加一下super.toString()(即同時輸出父類的信息,在發放拋出異常時,經過toString()方法打印其屬性值,便於排查問題)。
也可以使用apache common工具類庫的ReflectionToStringBuilder.toString(this)經過反射打印出類中的屬性,包括父類的屬性。
String的split方法 使用索引訪問String的split方法獲得的數組時,需作最後一個分隔符後有無內容的檢查,不然會有拋IndexOutOfBoundsException的風險;例:"a,b,c,,";
同名方法 當一個類中有多個構造方法,或者多個同名方法,這些方法應該按順序放置在一塊兒,便於閱讀。
類內方法定義順序 公有或保護方法 > 私有方法 > getter/setter方法。
getter/setter方法 setter方法中,參數名稱與類成員名稱一致,this.成員名=參數名,在getter/setter方法中,儘可能不要增長業務邏輯,增長排查問題的難度。
字符串聯接 在循環體內,字符串的聯接方式,使用StringBuilder的append方法進行擴展。反編譯出的字節碼文件顯示每次循環都會new一個StringBuilder對象,進行append操做,並調用toString方法返回String對象,形成內存資源浪費。
final關鍵字 final可提升程序響應效率,聲明成final的狀況:
1 不須要從新賦值的變量,包括類屬性、局部變量。
2 對象參數前加final,表示不容許修改引用的指向。 3 類方法肯定不容許被重寫。
clone方法 慎用Object的clone方法來拷貝對象,默認是淺拷貝,共享對象屬性引用,若想實現深拷貝需重寫clone方法實現屬性對象的拷貝。
類成員與方法訪問控制從嚴 1 不容許外部直接new建立對象,構造方法必須是private
2 工具類不容許有public 或 default構造方法
3 類非static成員變量而且與子類共享,必須是protected
4 類非static成員變量而且僅在本類使用,必須是private
5 類static成語言變量而且僅在本類使用,必須是privat
6 如果static成員變量,必須考慮是否爲final
7 類成員方法只供類內部調用,必須是private
8 類成員方法只對繼承類公開,那麼限制爲protected

(五)集合處理

類型 規範
hashCode和equals 1 只要重寫equals,必須重寫hashCode[equals 結果相同,hashCode必須一致;hashCode相同,equals不必定相同]
2 Set存儲的是不可重複的對象,依據hashCOde和equals進行判斷,因此Set存儲的對象必須重寫方法
3 若是自定義對象做爲Map的鍵,那麼必須重寫hashCode和equals
ArrayList的subList subList結果不可強轉爲ArrayList,不然會拋出ClassCastException異常:java.util.RandomAccessSubList cannot be cast to java.util.ArrayList;
說明:subList返回的是ArrayList的內部類SubList,並非ArrayList,而是ArrayList的一個視圖,對於SubList子列表的全部操做最終會反映到原列表上。
subList場景 在subList場景中,高度注意對原集合元素個數的修改,會致使子列表的遍歷、增長、刪除均產生ConcurrentModificationException異常。
集合轉數組 必須使用集合的toArray(T[] a),傳入的是類型徹底同樣的數組,大小就是list.size();
說明:調用toArray代餐方法,a.length小於集合size時,從新分配內存空間,返回新數組地址(長度爲集合size),a.length大於集合size時,設置[list.size()]的數組元素爲null,其餘數組元素保持原值,所以最好a長度與集合元素個數一致。
Arrays.asList() 使用工具類Arrays.asList()把數組轉換成集合時,沒法調用其修改集合相關的方法,它的add/remove/clear方法會拋出UnsupportedOperationException異常。
說明:asList的返回對象是一個Arrays內部類,並無實現集合的修改方法。Arrays.asList體現的是適配器模式,只是轉換接口,後臺的數據還是數組。
泛型通配符<? extends T> 泛型上限,用來接受返回的數據,此寫法的泛型集合不能使用add方法。
foreache循環 集合foreach底層是迭代器模式,在foreach循環中進行元素的remove/add操做可能會拋出異常,remove元素請使用Iterator方式,若是併發操做,須要對Iterator對象加鎖。
Comparator JDK7版本以上,Comparator要知足自反性,傳遞性,對稱性,否則Arrays.sort,Collections.sort會報IllegalArgumentException異常。
集合初始化 集合初始化時,儘可能指定集合初始值大小。
鍵值對集合遍歷 使用entrySet遍歷Map類集合KV,而不是keySet方式進行遍歷。
說明:keySet實際上是遍歷了2次,一次是轉爲Iterator對象,另外一次是從hashMap中取出key所對應的value,而entrySet只遍歷一次就把k,v都放到entry中,效率更高,若是是JDK8,使用Map.foreach方法。
Map類存儲null值 圖片描述
說明:不容許null值時,存儲null值會拋出NPE異常。
集合的有序性和穩定性 合理利用好集合的有序性(sort)和穩定性(order),皮面集合的無序性(unsort)何不穩定性(unorder)帶來的負面影響。
說明:穩定性指集合每次遍歷的元素次序是必定的。有序性是指遍歷的結果是按某種比較規則依次排序的。如:Array是order/unsort;HashMap是unorder/unsort;TreeSet是order/sort;
Set特性 利用Set元素惟一的特性,能夠快速對一個集合進行去重操做,避免使用List的contains方法進行遍歷、對比、去重操做。

併發處理

類型 規範
獲取單例對象 須要保證線程安全,其中非方法也要保證線程安全
說明:資源驅動類、工具類、單例工廠類都須要注意。
建立線程或線程池 建立線程或線程池時請指定有意義的線程名稱,方便出錯時回溯。
線程資源 線程資源必須經過線程池提供,不容許在應用中自行顯式建立線程。
說明:使用線程池的好處是減小在建立和銷燬線程上所花的時間以及系統資源的開銷,解決資源不足的問題。避免形成系統建立大量同類線程而致使消耗完內存或「過分切換」問題。
線程池建立 不容許使用Executors建立,而是經過ThreadPoolExecutor的方式,明確線程池的運行規則,規避資源耗盡的風險。
說明:FixedThreadPool 和SingleThreadPool 容許的請求隊列長度爲Integer.MAX_VALUE,可能會堆積大量請求,從而致使OOM。 CachedThreadPool 和ScheduledThreadPool容許的建立線程數量爲Integer.MAX_VALUE,可能會建立大量的線程,從而致使OOM。
SimpleDateFormat 是線程不安全的類,通常不要定義爲static變量,若是定義爲static,必須加鎖,或者使用DateUtils工具類,亦推薦使用ThreadLocal。
說明:若是是JDK8,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFirmatter。
高併發 高併發時,同步調用應該去考量鎖的性能損耗。能用無鎖數據結構,就不要用鎖;能鎖區塊,就不要鎖整個方法體;能用對象鎖,就不要用類鎖。
併發修改 併發修改同一記錄時,避免更新丟失,要麼在應用層加鎖,要麼在緩存加鎖,要麼在數據層使用樂觀鎖,使用version做爲更新依據。
說明:若是每次訪問衝突機率小於20%,推薦使用樂觀鎖,不然使用悲觀鎖。樂觀鎖的重試次數不能小於3次。
定時任務 多線程並行處理定時任務時,Timer運行多個TimeTask時,只要其中之一沒有捕獲拋出的異常,其餘任務便會自動終止運行,使用ScheduledExecutorService則沒有這個問題。
CountDownLatch 使用CountDownLatch進行異步轉同步操做,每一個線程退出前必須調用countDown方法,線程執行代碼注意catch異常,確保countDown方法能夠執行,避免主線程沒法執行至countDown方法,直到超時才返回結果。
說明:注意,子線程拋出異常堆棧,不能在主線程try-catch到。
Rondom 避免Random實例被多線程使用,雖然共享該實例是線程安全的,但會因競爭同一seed致使性能降低。
說明:Random實例包括java.util.Random和Math.random()實例。 在JDK7以後,能夠直接使用API ThreadLocalRandom,在JDK7以前,能夠作到每一個線程一個實例。
雙重檢查 經過雙重檢查鎖(double-checked locking)(在併發場景)實現延遲初始化的優化問題隱患,推薦問題解決方案中較爲簡單一種(JDK5以後),將目標屬性聲明爲volatile型。
volatile volatile解決多線程內存不可見問題。對於一寫多讀,是能夠解決變量同步問題,可是若是多寫,一樣沒法解決線程安全問題.若是是i++操做,經過AtomicInteger.addAndGet(1);若是是JDK8,推薦使用LongAdder對象,比AtomicLong性能更好(減小樂觀鎖的重試次數)。
HashMap HashMap在容量不夠進行resize時因爲高併發可能出現死鏈,致使CPU飆升,在開發過程當中注意規避此風險。
ThreadLocal ThreadLocal沒法解決共享對象的更新問題,ThreadLocal對象建議使用static修飾,這個變量是針對一個線程內全部操做共有的,因此設置爲靜態變量,全部此類實例共享此靜態變量,也就是說類第一次被使用時裝載,只分配一塊存儲空間,全部此類的對象(同一線程內)均可以操做這個變量。

控制語句

類型 規範
switch 在switch塊中,每一個case要麼經過break/return等來終止,要麼註釋說明程序將繼續執行到哪個case爲止;在一個switch塊內,都必須包含一個default語句而且放在最後,即便什麼代碼也沒有。
if/else/for/while/do 在if/else/for/while/do語句中必須使用大括號,即便只有一行代碼
else 推薦儘可能少用else,if-else 可改寫爲 if() { return} //接着寫else業務邏輯
說明:若是非得使用if..else if..else,勿超過3層,超過請使用衛語句,或者狀態模式來實現。
條件判斷語句 不要在條件判斷中執行復雜語句,將複雜語句的結果賦值給一個有意義的布爾變量名,以提升可讀性。
循環體 循環體重的語句要考量性能,如下操做盡可能移至循環體外處理,定義對象、變量、獲取數據庫鏈接,進行沒必要要的try-catch操做(這個try-catch是否能夠移至循環體外)
接口入參保護 對接口接受參數進行檢驗,避免錯誤不合理的參數,這種場景常見的是用於作批量操做的接口。
參數校驗 場景:1 調用頻次低的方法。
2 執行時間開銷大,參數校驗時間幾乎能夠忽略不計,但由於參數錯誤致使中間執行回退或者錯誤,得不償失。
3 須要極高穩定性和可用性的方法。
4 對外提供的開發接口,無論是RPC/API/HTTP接口。
敏感權限入口。
不須要參數校驗 場景:1 既有可能被循環調用的方法,不建議對參數進行校驗。但在方法說明裏面必須註明外部參數檢查。
2 底層方法調用頻度都比較高,通常不校驗。
3 被聲明成private只會被本身代碼調用的方法時,可以確認調用方法的傳入參數作過檢查或確定不會有問題,此時能夠不校驗參數。

註釋規約

類型 規範
類、類屬性、類方法 註釋必須使用Javadoc規範,/* /,不得使用//xxx
抽象方法(接口方法) 必需要用Javadoc註釋,除了返回值、參數、異常說明外,還必須指出該方法作什麼事情,實現什麼功能。
對子類的實現要求,或者調用注意事項,請一併說明。
全部的類都必須添加建立者信息。
方法內部註釋 方法內部單行註釋在被註釋語句上方另起一行,使用//註釋。方法內部多行註釋 使用/ /註釋,注意與代碼對齊。
枚舉字段 全部枚舉類型字段必需要有註釋,說明每一個數據項的用途。
英文註釋 英文水平很差,不如用中文註釋把問題說清楚,專有名詞與關鍵字保持英文原文。
代碼修改 代碼修改的同時,註釋也要進行相應的修改,尤爲是參數、返回值、異常、核心邏輯等的修改。
註釋掉的代碼 儘可能配合說明,而不是簡單的註釋掉
說明:代碼被註釋有兩種可能,1後續恢復此段代碼邏輯 2永久不用 前者若是不備註信息,難以知曉註釋動機,後者建議直接刪掉(代碼倉庫保存歷史代碼)
註釋要求 1、準確反應設計思想和代碼邏輯;2、描述業務含義,使閱讀者能迅速瞭解代碼背後信息。能夠幫助本身後期理解當時思路;也可給繼任者快速接替本身工做。
有效註釋 好的命名、代碼結構是自解釋的,註釋力求精簡準確、表達到尾。避免濫用。
特殊註釋標記 1 TODO(待辦事宜):(標記人、標記時間、[預計處理時間])
2 FIXME(錯誤,不能工做):(標記人、標記時間、[預計處理時間])

其餘

類型 規範
正則表達式 利用好其預編譯功能,能夠有效加快正則匹配速度
不要再方法體內定義: Pattern pattern = Pattern.compile(規則);
velocity velocity調用POJO類的屬性時,建議直接使用屬性名取值便可,模板引擎會自動按規範調用POJO的getxxx(),若是是boolean基本數據類型變量(boolean命名不須要加is前綴),會自動調用isxxx(),若是是Boolean包裝類對象,優先調用getxxx()。
頁面變量 若是後臺輸送給頁面的變量必須加$!{var} 中間的感嘆號,若是var==null或不存在,那麼${var}會直接顯示在頁面上
相關文章
相關標籤/搜索