Java開發(fā)規(guī)范
1.命名風(fēng)格
- 參數(shù)名,變量名以小駝峰lowerCamelCase規(guī)范:
profileName
- 類名以大駝峰UpperCamelCase規(guī)范:
UserDO
- 常量名大寫,單詞下劃線隔開
MAX_STOCK_COUNT
- 使用英文命名,不能出現(xiàn)拼音,以最為準(zhǔn)確的翻譯為準(zhǔn).
- 抽象類使用
Abstrac
t或者Base
開頭,異常類使用Exception
結(jié)束
- 數(shù)組使用類型[] 變量名方式:
String[] names
,而不是String args[]
- 包名使用小寫,不加下劃線.
- 除了通用縮寫方式,盡量使用完整單詞組合命名.通用縮寫見下表.
- 不能出現(xiàn)int a這樣的"未知"變量名,必須使用一個(gè)可以表達(dá)含義的單詞或短語(yǔ).
- 接口中的方法和變量不加修飾符(方法默認(rèn)public abstract,變量默認(rèn)public static final)
- 當(dāng)使用設(shè)計(jì)模式時(shí),推薦類名使用設(shè)計(jì)模式名
OrderFactory,LoginProxy,DataObserver
- 業(yè)務(wù)類接口以I開頭
IPresenter
,實(shí)現(xiàn)以ImplLoginPresenterImpl
結(jié)尾.
- 枚舉類以
Enum
結(jié)尾.枚舉成員大寫加下劃線分隔.
- 方法命名規(guī)范:
(1). 獲取單個(gè)對(duì)象以get做前綴
(2). 獲取多個(gè)對(duì)象以list做前綴,復(fù)數(shù)形式結(jié)尾: listBooks
(3). 獲取統(tǒng)計(jì)值用count做前綴
(4). 插入方法以save/insert做前綴
(5). 刪除方法以remove/delete做前綴
(6). 修改方法以u(píng)pdate做前綴
- 領(lǐng)域?qū)ο竺?guī)范:
(1). 數(shù)據(jù)庫(kù)對(duì)象xxxDO
(2). 頁(yè)面展示對(duì)象xxxVO
(3). 上傳接口對(duì)象xxxReq
(4). 接口獲取對(duì)象xxxRes
(5). 業(yè)務(wù)對(duì)象xxxBO
2.常量定義
- 在long或Long類型賦值時(shí),數(shù)值使用大寫L,而不是小寫l,小寫l容易和1混淆
- 常量類需要按功能分類,不能使用大而全的常量類.例:緩存使用CacheConsts,配置使用ConfigConsts
- 如果變量值僅在較小規(guī)模的固定范圍內(nèi)變化,使用enum,如季節(jié),星期,生命周期,業(yè)務(wù)狀態(tài)等.
3.代碼格式
- 文件編碼使用UTF-8,IDEA設(shè)置:
(1). Preference->Editor->Code Style-> File Encodings "Global Encoding","Project Encoding","Default encoding for properties files"都設(shè)置為"UTF-8"UTF-8"
(2). "Create UTF-8 files"設(shè)置為"with No BOM"
- 空格使用Unix格式,IDEA設(shè)置:
Preference->Editor->Code Style-> Line separator設(shè)置為"Unix and OS X (\n)
- 必須使用4個(gè)空格縮進(jìn),不能使用Tab,IDEA設(shè)置:
Preference->Editor->Code Style->Java -> Tabs and Indents -> "Tab size"和"Indent"設(shè)置為4,勿勾選"Use tab character"
- 每行超出120個(gè)字符換行,換行規(guī)則:
(1). 換行縮進(jìn)4個(gè)空格,再換行不再縮進(jìn)
(2). 運(yùn)算符和下文一起換行
(3). 方法調(diào)用的.與方法一起換行
(4). 方法內(nèi)多參數(shù)需換行時(shí),在逗號(hào)后換行
IDEA設(shè)置:
(1). Preference->Editor->Code Style-> Hard wrap at 設(shè)置為120
(2). Preference->Editor->Code Style->Java ->Wrapping and Braces -> 勾選"Line breaks"和"Ensure right margin is not exceeded"
- 方法內(nèi)部不同邏輯,不同語(yǔ)義,不同業(yè)務(wù)之間可以使用換行,代碼任意位置不能出現(xiàn)多余1行的空行.IDEA設(shè)置:
Preference->Editor->Code Style->Java->Blank Lines->所有超過(guò)1的選項(xiàng)設(shè)置為1.
- 空格使用規(guī)范:
(1). if/for/while/switch/do 等保留字與括號(hào)之間都必須加空格吹艇。
(2). 小括號(hào)內(nèi)左右第一個(gè)字符和小括號(hào)間不留空格
(3). 左大括號(hào)前加空格
(4). 二目三目運(yùn)算符的左右兩邊都要加空格
(5). 雙斜線和注釋內(nèi)容間僅使用一個(gè)空格
(6). 方法參數(shù)間使用一個(gè)空格
- 大括號(hào)使用規(guī)范:
(1). 左大括號(hào)前不換行
(2). 左大括號(hào)后換行
(3). 右大括號(hào)前有else等不換行
(4). 右大括號(hào)表示終止需換行
(5). 大括號(hào)內(nèi)為空,可寫成{},并不換行
- 推薦單個(gè)方法勿超過(guò)80行,超過(guò)80行考慮提取方法,保持單一責(zé)任原則.
4. OOP 規(guī)約
- 所有靜態(tài)變量,常量,方法,都使用類名調(diào)用,勿使用對(duì)象調(diào)用.避免增加編譯器解析成本.
- 所有覆寫方法,需要加上@Override注解,避免方法名寫錯(cuò),編譯時(shí)不報(bào)錯(cuò).推薦使用快捷鍵調(diào)用"Override Members"覆寫方法,避免出錯(cuò).
- 避免使用Object作為參數(shù),盡量不適用可變參數(shù).
- 不能使用過(guò)時(shí)的類或方法.
- Object的equals方法容易拋空指針異常,應(yīng)使用常量來(lái)調(diào)用equals:"cache".equals(xxx),或者使用Objects.equals(a,b)
- POJO類屬性強(qiáng)制使用包裝數(shù)據(jù)類型,如當(dāng)數(shù)據(jù)庫(kù)查詢時(shí)結(jié)果可能為null,使用基本數(shù)據(jù)類型去接收會(huì)有NPE風(fēng)險(xiǎn).并且基本數(shù)據(jù)類型的默認(rèn)值可能會(huì)帶來(lái)錯(cuò)誤信息,比如當(dāng)調(diào)用接口沒(méi)有返回值時(shí),默認(rèn)的0,false等會(huì)帶來(lái)歧義.null值表示出額外的信息:調(diào)用失敗,服務(wù)器未返回該值等.
- 構(gòu)造方法里不能加入業(yè)務(wù)邏輯,初始化邏輯應(yīng)放在init方法中.
- POJO類必須重寫toString()方法(Kotlin的data類默認(rèn)已添加該方法,無(wú)需手動(dòng)添加)
- 重載方法應(yīng)按順序放在一起,構(gòu)造方法相同.在此基礎(chǔ)上的方法置放順序:public,proteced > private > getter/setter
- getter/setter方法應(yīng)保持簡(jiǎn)單的get/set動(dòng)作,不應(yīng)插入業(yè)務(wù)邏輯.
- 循環(huán)體內(nèi),字符串的連接使用StringBuilder的append方法,使用字符串直接+連接會(huì)造成每次循環(huán)new出StringBuilder對(duì)象.(Kotlin可使用"${var1}var2"方式連接)
- 方法,屬性權(quán)限應(yīng)給滿足使用的最小權(quán)限.
(1). 類內(nèi)使用:private
(2). 包內(nèi)和子類使用:protected.
過(guò)于寬泛的權(quán)限會(huì)導(dǎo)致不當(dāng)調(diào)用泛濫,不利于解耦.(一旦在其他地方被調(diào)用,這個(gè)方法,屬性就不止屬于類自己了)
- 不能再foreach循環(huán)里進(jìn)行元素的remove/add操作.可能會(huì)引起運(yùn)行時(shí)異常.
- 為了降低記憶負(fù)擔(dān),Map中不要使用null作為key,只有HashMap和TreeMap可以存儲(chǔ)null的value.
- 合理利用好集合的有序性(sort)和穩(wěn)定性(order),避免集合的無(wú)序性(unsort)和
不穩(wěn)定性(unorder)帶來(lái)的負(fù)面影響。
有序性是指遍歷的結(jié)果是按某種比較規(guī)則依次排列的鼻忠。穩(wěn)定性指集合每次遍歷的元素次
序是一定的兔院。如:ArrayList 是 order/unsort;HashMap 是 unorder/unsort袍暴;TreeSet 是order/sort踩晶。
- 可以用用Set的唯一性快速去重,不要使用List的contains方法進(jìn)行遍歷對(duì)比去重.
- 表達(dá)異常的分支,少用if-else,減少if-else嵌套,嵌套不能超過(guò)3層,消滅箭頭語(yǔ)句,盡量使用衛(wèi)語(yǔ)句(剪枝邏輯):
No:
if(condition1){
} esle if(condition2) {
} else if(condition3) {
}
Yes:
if(condition1){
}
if(condition2){
}
if(condition3){
}
- 不要直接使用復(fù)雜的判斷邏輯,將復(fù)雜的判斷表達(dá)式賦值給一個(gè)有意義的布爾變量,調(diào)代碼可讀性.
正例:
// 偽代碼如下
final boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) {
...
}
反例:
if ((file.open(fileName, "w") != null) && (...) || (...)) {
...
}
- 校驗(yàn)參數(shù)規(guī)范:
(1). 執(zhí)行流程較為復(fù)雜的方法需要進(jìn)行參數(shù)校驗(yàn)(FastFail)
(2). 與用戶輸入相關(guān)方法需校驗(yàn)參數(shù).
(3). 對(duì)外提供的開放接口需校驗(yàn)參數(shù).
(4). 較為底層且調(diào)用次數(shù)頻繁方法不需要校驗(yàn)參數(shù).
5. 注釋規(guī)約
- 類、類屬性唧躲、類方法的注釋必須使用 Javadoc 規(guī)范,使用/*內(nèi)容/格式伸眶,不得使用
// xxx 方式惊窖。
說(shuō)明:在 IDE 編輯窗口中,Javadoc方式會(huì)提示相關(guān)注釋厘贼,生成Javadoc可以正確輸出相應(yīng)注釋界酒;在IDE中,工程調(diào)用方法時(shí)嘴秸,不進(jìn)入方法即可懸浮提示方法毁欣、參數(shù)庇谆、返回值的意義,提高閱讀效率凭疮。
- 所有的抽象方法(包括接口中的方法)必須要用Javadoc注釋饭耳、除了返回值、參數(shù)执解、異常說(shuō)明外寞肖,還必須指出該方法做什么事情,實(shí)現(xiàn)什么功能衰腌。
說(shuō)明:對(duì)子類的實(shí)現(xiàn)要求新蟆,或者調(diào)用注意事項(xiàng),需一并說(shuō)明右蕊。
- 方法內(nèi)部單行注釋琼稻,在被注釋語(yǔ)句上方另起一行,使用//注釋饶囚。方法內(nèi)部多行注釋
使用/* */注釋帕翻,注意與代碼對(duì)齊。
- 注釋掉的代碼用注釋說(shuō)明注釋原因,注釋原因用///注釋,如果不再使用,刪除該代碼,使用版本控制追溯.
- 對(duì)于注釋的要求:
(1). 能夠準(zhǔn)確反應(yīng)設(shè)計(jì)思想和代碼邏輯
(2). 能夠描述業(yè)務(wù)含義萝风,使別的程序員能夠迅速了解到代碼背后的信息嘀掸。
(3). 保持和代碼的同步.
(4). 盡量使用常用,簡(jiǎn)單的英語(yǔ)進(jìn)行注釋.可搭配翻譯使用,避免中式英語(yǔ).
(5). 使用最簡(jiǎn)練的語(yǔ)言寫注釋,好的命名、代碼結(jié)構(gòu)是自解釋的闹丐,避免過(guò)多過(guò)濫的注釋.
反例:
// put elephant into fridge
put(elephant, fridge);
方法名 put横殴,加上兩個(gè)有意義的變量名 elephant 和 fridge被因,已經(jīng)說(shuō)明了這是在干什么卿拴,語(yǔ)
義清晰的代碼不需要額外的注釋。
- 特殊注釋標(biāo)記
(1). 待辦事宜(TODO):( 標(biāo)記人梨与,標(biāo)記時(shí)間堕花,[預(yù)計(jì)處理時(shí)間])
(2). 錯(cuò)誤,不能工作(FIXME):(標(biāo)記人粥鞋,標(biāo)記時(shí)間缘挽,[預(yù)計(jì)處理時(shí)間])
6. 異常處理規(guī)約
- 異常因使用最小粒度進(jìn)行捕獲,不能使用一個(gè)exception進(jìn)行捕獲.注意多個(gè)異常排列的順序.
- 捕獲異常應(yīng)盡量catch最小的單元,不要catch過(guò)多內(nèi)容.
- 捕獲異常之后必須處理.推薦異常進(jìn)行日志記錄上報(bào)(Do not swallow)
- 資源需要在finally中釋放,推薦使用try-with-resource的方式.
- 級(jí)聯(lián)調(diào)用 obj.getA().getB().getC();一連串調(diào)用呻粹,易產(chǎn)生 NPE壕曼。使用 JDK8 的 Optional 類來(lái)防止 NPE 問(wèn)題。(Kotlin可使用?.調(diào)用方式處理)
if(obj == null){
return;
}
if(a == null){
return;
}
if(b == null){
return;
}
b.getC();
if(obj?.getA()?.getB()?.getC() == null){
return
}
obj!!.getA();
7. 日志規(guī)約
- 日志文件至少保存15天,有些異常是以"周"為頻次發(fā)生的.
- 對(duì) trace/debug/info 級(jí)別的日志輸出等浊,必須使用條件輸出形式或者使用占位符的方
式腮郊。
反例
logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
正例:(條件)建設(shè)采用如下方式
if (logger.isDebugEnabled()) {
logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
}
正例:(占位符)
logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
Kotlin中可采取
logger.debug("Processing trade with id: ${id} and symbol: ${symbol}");
- 日志不可重復(fù)打印,冗余打印,保持精簡(jiǎn).
- 異常日志應(yīng)記錄必要的現(xiàn)場(chǎng)信息和堆棧信息
正例:
logger.error(各類參數(shù)或者對(duì)象 toString() + "_" + e.getMessage(), e);
- 生產(chǎn)環(huán)境應(yīng)關(guān)閉debug日志.(遠(yuǎn)程調(diào)試除外)
討論
- 所有的枚舉類型字段必須要有注釋,說(shuō)明每個(gè)數(shù)據(jù)項(xiàng)的用途筹燕。
- 每個(gè)switch需要帶上default,case語(yǔ)句如果沒(méi)有break語(yǔ)句,需要在末尾注釋// fall down
-
TODO:單元測(cè)試規(guī)約
參考:
阿里巴巴java開發(fā)手冊(cè)
插件使用文檔
阿里巴巴Android開發(fā)手冊(cè)