作者丨silianpan
來源:https://juejin.im/post/5ada99fff265da0b8a672fbd
基於阿里巴巴JAVA開發規範整理
一、命名風格
【強制】類名使用 UpperCamelCase 風格,必須遵從駝峰形式,但以下情形例外:DO / BO / DTO / VO / AO
【強制】方法名、參數名、成員變量、局部變量都統一使用 lowerCamelCase 風格,必須遵從 駝峰形式。
【強制】常量命名全部大寫,單詞間用下劃線隔開,力求語義表達完整清楚,不要嫌名字長。
【強制】抽象類命名使用 Abstract 或 Base 開頭;異常類命名使用 Exception 結尾;測試類命名以它要測試的類的名稱開始,以 Test 結尾。
【強制】Model 類中布爾類型的變量,都不要加 is,否則部分框架解析會引起序列化錯誤。
【強制】對於 Service 和 DAO 類,基於 SOA 的理念,暴露出來的服務一定是接口,內部的實現類用 Impl 的後綴與接口區別。正例:CacheManagerImpl 實現 CacheManager 接口。
【推薦】為了達到代碼自解釋的目標,任何自定義編程元素在命名時,使用儘量完整的單詞組合來表達其意。
正例:從遠程倉庫拉取代碼的類命名為PullCodeFromRemoteRepository
【推薦】接口類中的方法和屬性不要加任何修飾符號(public 也不要加),保持代碼的簡潔 性,並加上有效 的Javadoc 注釋。儘量不要在接口裡定義變量,如果一定要定義變量,肯定是 與接口方法相關,並且是整個應用的基礎常量。
【參考】枚舉類名建議帶上 Enum 後綴,枚舉成員名稱需要全大寫,單詞間用下劃線隔開。
【參考】各層命名規約:
Service/DAO 層方法命名規約
二、變量定義
【推薦】不要使用一個常量類維護所有常量,按常量功能進行歸類,分開維護。說明:大而全的常量類,非得使用查找功能才能定位到修改的常量,不利於理解和維護。
三、代碼格式
【強制】大括號的使用約定。如果是大括號內為空,則簡潔地寫成{}即可,不需要換行;如果 是非空代碼塊則:
【強制】 左小括號和字符之間不出現空格;同樣,右小括號和字符之間也不出現空格。
【強制】if/for/while/switch/do 等保留字與括號之間都必須加空格。
【強制】任何二目、三目運算符的左右兩邊都需要加一個空格。
【強制】採用 4 個空格縮進,禁止使用 tab 字符。
【強制】注釋的雙斜線與注釋內容之間有且僅有一個空格。
正例:// 注釋內容,注意在//和注釋內容之間有一個空格。
【強制】方法參數在定義和傳入時,多個參數逗號後邊必須加空格。
【強制】IDE 的 text file encoding 設置為 UTF-8; IDE 中文件的換行符使用 Unix 格式,不要使用 Windows 格式。
【推薦】方法體內的執行語句組、變量的定義語句組、不同的業務邏輯之間或者不同的語義之間插入一個空行。相同業務邏輯和語義之間不需要插入空行。
四、OOP規約
【強制】所有的覆寫方法,必須加@Override 註解。
【強制】不能使用過時的類或方法。
【強制】Object 的 equals 方法容易拋空指針異常,應使用常量或確定有值的對象來調用 equals。
【強制】所有的相同類型的包裝類對象之間值的比較,全部使用 equals 方法比較。
【強制】RPC 方法的返回值和參數必須使用包裝數據類型。
【強制】構造方法裡面禁止加入任何業務邏輯,如果有初始化邏輯,請放在 init 方法中。
【推薦】當一個類有多個構造方法,或者多個同名方法,這些方法應該按順序放置在一起, 便於閱讀。
【推薦】循環體內,字符串的連接方式,使用 StringBuilder 的 append 方法進行擴展。
String str = "start";
for (int i = 0; i < 100; i++) {
str = str + "hello";
}
【推薦】慎用 Object 的 clone 方法來拷貝對象。說明:對象的 clone 方法默認是淺拷貝,若想實現深拷貝需要重寫 clone 方法實現屬性對象 的拷貝。
五、集合處理
【強制】使用集合轉數組的方法,必須使用集合的 toArray(T[] array),傳入的是類型完全一樣的數組,大小就是 list.size()。
Listlist = new ArrayList (2);
list.add("guan");
list.add("bao");
String[] array = new String[list.size()];
array = list.toArray(array);
【強制】不要在 foreach 循環里進行元素的 remove/add 操作。remove 元素請使用 Iterator方式,如果並發操作,需要對 Iterator 對象加鎖。
【推薦】使用 entrySet 遍歷 Map 類集合 KV,而不是 keySet 方式進行遍歷。
六、控制語句
【強制】在一個 switch 塊內,每個 case 要麼通過 break/return 等來終止,要麼注釋說明程序將繼續執行到哪一個 case 為止;在一個 switch 塊內,都必須包含一個 default 語句並且 放在最後,即使它什麼代碼也沒有。
【強制】在 if/else/for/while/do 語句中必須使用大括號。即使只有一行代碼,避 單行的編碼方式:if (condition) statements;
【推薦】除常用方法(如 getXxx/isXxx)等外,不要在條件判斷中執行其它複雜的語句,將復 雜邏輯判斷的結果賦值給一個有意義的布爾變量名,以提高可讀性。
//偽代碼如下
final boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) {
...
}
if ((file.open(fileName, "w") != null) && (...) || (...)) {
...
}
【推薦】循環體中的語句要考量性能,以下操作儘量移至循環體外處理,如定義對象、變量、 獲取資料庫連接,進行不必要的 try-catch 操作(這個 try-catch 是否可以移至循環體外)。
【參考】下列情形,需要進行參數校驗:
七、注釋規約
【強制】類、類屬性、類方法的注釋必須使用 Javadoc 規範,使用/*內容/ 格式,不得使用 // xxx 方式。
【強制】所有的抽象方法(包括接口中的方法)必須要用 Javadoc 注釋、除了返回值、參數、 異常說明外,還必須指出該方法做什麼事情,實現什麼功能。
【強制】所有的類都必須添加創建者和創建日期。
【強制】方法內部單行注釋,在被注釋語句上方另起一行,使用//注釋。方法內部多行注釋 使用/* */注釋,注意與代碼對齊。
【強制】所有的枚舉類型欄位必須要有注釋,說明每個數據項的用途。
【推薦】代碼修改的同時,注釋也要進行相應的修改,尤其是參數、返回值、異常、核心邏輯 等的修改。
【參考】謹慎注釋掉代碼。在上方詳細說明,而不是簡單地注釋掉。如果無用,則刪除。
【參考】對於注釋的要求:第一、能夠準確反應設計思想和代碼邏輯;第二、能夠描述業務含 義,使別的程式設計師能夠迅速了解到代碼背後的信息。完全沒有注釋的大段代碼對於閱讀者形同 天書,注釋是給自己看的,即使隔很長時間,也能清晰理解當時的思路;注釋也是給繼任者看 的,使其能夠快速接替自己的工作。
【參考】好的命名、代碼結構是自解釋的,注釋力求精簡準確、表達到位。避免出現注釋的 一個極端:過多過濫的注釋,代碼的邏輯一旦修改,修改注釋是相當大的負擔。
【參考】特殊注釋標記,請註明標記人與標記時間。注意及時處理這些標記,通過標記掃描, 經常清理此類標記。線上故障有時候就是來源於這些標記處的代碼。
八、其他
【強制】在使用正則表達式時,利用好其預編譯功能,可以有效加快正則匹配速度。說明:不要在方法體內定義:Pattern pattern = Pattern.compile(規則);
【強制】注意 Math.random() 這個方法返回是 double 類型,注意取值的範圍 0≤x<1(能夠 取到零值,注意除零異常),如果想獲取整數類型的隨機數,不要將 x 放大 10 的若干倍然後 取整,直接使用 Random 對象的 nextInt 或者 nextLong 方法。
【強制】獲取當前毫秒數 System.currentTimeMillis(); 而不是 new Date().getTime();
【推薦】任何數據結構的構造或初始化,都應指定大小,避免數據結構無限增長吃光內存。
九、異常處理
【強制】捕獲異常是為了處理它,不要捕獲了卻什麼都不處理而拋棄之,如果不想處理它,請 將該異常拋給它的調用者。最外層的業務使用者,必須處理異常,將其轉化為用戶可以理解的 內容。
十、MySQL資料庫
建立表規約
【強制】表名、欄位名必須使用小寫字母或數字,禁止出現數字開頭,禁止兩個下劃線中間只 出現數字。資料庫欄位名的修改代價很大,因為無法進行預發布,所以欄位名稱需要慎重考慮。
【強制】禁用保留字,如 desc、range、match、delayed 等,請參考 MySQL 官方保留字。
【強制】主鍵索引名為 pk_欄位名;唯一索引名為 uk_欄位名;普通索引名則為 idx_欄位名。說明:pk_ 即 primary key;uk_ 即 unique key;idx_ 即 index 的簡稱。
【強制】小數類型為 decimal,禁止使用 float 和 double。
【強制】如果存儲的字符串長度幾乎相等,使用 char 定長字符串類型。
【強制】varchar 是可變長字符串,不預先分配存儲空間,長度不要超過 5000,如果存儲長度大於此值,定義欄位類型為 text。
【強制】表必備三個欄位:id,create_time, update_time, delete_flag
【強制】對於Boolean型的欄位,採用decimal類型
【強制】表和欄位都需要添加註釋信息。
【推薦】單表行數超過 500 萬行或者單表容量超過 2GB,才推薦進行分庫分表。說明:如果預計三年後的數據量根本達不到這個級別,請不要在創建表時就分庫分表。
【參考】合適的字符存儲長度,不但節約資料庫表空間、節約索引存儲,更重要的是提升檢 索速度。
索引規約
【強制】業務上具有唯一特性的欄位,即使是多個欄位的組合,也必須建成唯一索引。
【強制】超過三個表禁止 join。需要 join 的欄位,數據類型必須絕對一致;多表關聯查詢時, 保證被關聯的欄位需要有索引。
【強制】在 varchar 欄位上建立索引時,必須指定索引長度,沒必要對全欄位建立索引,根據 實際文本區分度決定索引長度即可。
【參考】創建索引時避免有如下極端誤解:
SQL語句
【強制】不要使用 count(列名)或 count(常量)來替代 count(),count()是 SQL92 定義的標準統計行數的語法,跟資料庫無關,跟 NULL 和非 NULL 無關。
【強制】count(distinct col) 計算該列除 NULL 之外的不重複行數,注意 count(di col1, col2) 如果其中一列全為 NULL,那麼即使另一列有不同的值,也返回為 0。
【強制】當某一列的值全是 NULL 時,count(col)的返回結果為 0,但 sum(col)的返回結果為NULL.
【強制】不得使用外鍵與級聯,一切外鍵概念必須在應用層解決。
【強制】禁止使用存儲過程,存儲過程難以調試和擴展,更沒有移植性。
【推薦】in 操作能避免則避免,若實在避免不了,需要仔細評估 in 後邊的集合元素數量,控 制在 1000 個之內。
【參考】如果有全球化需要,所有的字符存儲與表示,均以 utf-8 編碼,注意字符 的區別。
【強制】更新數據表記錄時,必須同時更新記錄對應的 update_time 欄位值為當前時間。
【參考】@Transactional 事務不要濫用。事務會影響資料庫的 QPS,另外使用事務的地方需 要考慮各方面的回滾方案,包括緩存回滾、搜尋引擎回滾、消息補償、統計修正等。