告別編碼5分鐘,命名2小時(shí)!史上超全的Java命名規(guī)范參考!
簡潔清爽的代碼風(fēng)格應(yīng)該是大多數(shù)工程師所期待的。在工作中筆者常常因?yàn)槠鹈侄m結(jié),命名已經(jīng)成為我工作中的攔路虎,夸張點(diǎn)可以說是編程5分鐘,命名兩小時(shí)!
每個(gè)公司都有不同的標(biāo)準(zhǔn),目的是為了保持統(tǒng)一,減少溝通成本,提升團(tuán)隊(duì)研發(fā)效能。所以本文中是筆者結(jié)合阿里巴巴開發(fā)規(guī)范,以及工作中的見聞針對(duì)Java領(lǐng)域相關(guān)命名進(jìn)行整理和總結(jié),僅供參考。
一,Java中的命名規(guī)范
好的命名能體現(xiàn)出代碼的特征,含義或者是用途,讓閱讀者可以根據(jù)名稱的含義快速厘清程序的脈絡(luò)。不同語言中采用的命名形式大相徑庭,Java中常用到的命名形式共有三種,既首字母大寫的UpperCamelCase,首字母小寫的lowerCamelCase以及全部大寫的并用下劃線分割單詞的UPPERCAMELUNSER_SCORE。通常約定,類一般采用大駝峰命名,方法和局部變量使用小駝峰命名,而大寫下劃線命名通常是常量和枚舉中使用。
| 類型(名) | 約束 | 例 |
|---|---|---|
| 項(xiàng)目 | 全部小寫 多個(gè)單詞用中劃線分隔‘-’ | spring-cloud |
| 包 | 全部小寫 | com.alibaba.fastjson |
| 類 | 單詞首字母大寫 | Feature, FieldDeserializer |
| 變量 | 首字母小寫 多個(gè)單詞組成時(shí), 除首個(gè)單詞 其他單詞首字母都要大寫 | password,? userName |
| 常量 | 全部大寫,多個(gè)單詞,用'_'分隔 | CACHEEXPIREDTIME |
| 方法 | 同變量 | read(),? getById(Long id) |
二,包命名
包名統(tǒng)一使用小寫,點(diǎn)分隔符之間有且僅有一個(gè)自然語義的英文單詞或者多個(gè)單詞自然連接到一塊(如 springframework,deepspace不需要使用任何分割)。包名統(tǒng)一使用單數(shù)形式,如果類命有復(fù)數(shù)含義,則可以使用復(fù)數(shù)形式。
包名的構(gòu)成可以分為以下幾四部分【前綴】 【發(fā)起者名】【項(xiàng)目名】【模塊名】。常見的前綴可以分為以下幾種:
| 前綴 | 例 | 含義 |
|---|---|---|
| indi 或 onem | indi.發(fā)起者名.項(xiàng)目名.模塊名.…… | 個(gè)體項(xiàng)目 個(gè)人發(fā)起,但非自己獨(dú)自完成 可公開或私有項(xiàng)目, copyright主要屬于發(fā)起者。 |
| pers | pers.個(gè)人名.項(xiàng)目名.模塊名.…… | 個(gè)人項(xiàng)目 指個(gè)人發(fā)起,獨(dú)自完成, 可分享的項(xiàng)目 copyright主要屬于個(gè)人 |
| priv | priv.個(gè)人名.項(xiàng)目名.模塊名.…… | 私有項(xiàng)目,指個(gè)人發(fā)起,獨(dú)自完成 非公開的私人使用的項(xiàng)目, copyright屬于個(gè)人。 |
| team | team.團(tuán)隊(duì)名.項(xiàng)目名.模塊名.…… | 團(tuán)隊(duì)項(xiàng)目,指由團(tuán)隊(duì)發(fā)起 并由該團(tuán)隊(duì)開發(fā)的項(xiàng)目 copyright屬于該團(tuán)隊(duì)所有 |
| 頂級(jí)域名 | com.公司名.項(xiàng)目名.模塊名.…… | 公司項(xiàng)目 copyright由項(xiàng)目發(fā)起的公司所有 |
三,類命名
類名使用大駝峰命名形式,類命通常時(shí)名詞或名詞短語,接口名除了用名詞和名詞短語以外,還可以使用形容詞或形容詞短語,如Cloneable,Callable等,表示實(shí)現(xiàn)該接口的類有某種功能或能力。對(duì)于測(cè)試類則以它要測(cè)試的類開頭,以Test結(jié)尾,如HashMapTest。
對(duì)于一些特殊特有名詞縮寫也可以使用全大寫命名,比如XMLHttpRequest,不過筆者認(rèn)為縮寫三個(gè)字母以內(nèi)都大寫,超過三個(gè)字母則按照要給單詞算。這個(gè)沒有標(biāo)準(zhǔn)如阿里巴巴中fastjson用JSONObject作為類命,而google則使用JsonObjectRequest命名,對(duì)于這種特殊的縮寫,原則是統(tǒng)一就好。
| 屬性(類) | 約束 | 例 |
|---|---|---|
| 抽象 | Abstract? 或 Base 開頭 | BaseUserService |
| 枚舉 | Enum 作為后綴 | OSType |
| 工具 | Utils作為后綴 | StringUtils |
| 異常 | Exception結(jié)尾 | RuntimeException |
| 接口實(shí)現(xiàn) | 接口名+ Impl | UserServiceImpl |
| 領(lǐng)域模型相 | /DO/DTO/VO/DAO | 正例:UserDAO 反例:UserDao |
| 設(shè)計(jì)模式相關(guān) | Builder,F(xiàn)actory等 | 當(dāng)使用到設(shè)計(jì)模式時(shí) 要使用對(duì)應(yīng)的設(shè)計(jì)模式作為后綴 如ThreadFactory |
| 處理特定功能 | Handler,Predicate Validator | 表示處理器,校驗(yàn)器,斷言 這些類工廠還有配套的方法名 如handle,predicate,validate |
| 測(cè)試 | Test后綴 | UserServiceTest 表示用來測(cè)試UserService類的 |
| MVC分層 | Controller,Service ServiceImpl,DAO 后綴 | UserManageController UserManageDAO |
四,方法
方法命名采用小駝峰的形式,首字小寫,往后的每個(gè)單詞首字母都要大寫。和類名不同的是,方法命名一般為動(dòng)詞或動(dòng)詞短語,與參數(shù)或參數(shù)名共同組成動(dòng)賓短語,即動(dòng)詞 + 名詞。一個(gè)好的函數(shù)名一般能通過名字直接獲知該函數(shù)實(shí)現(xiàn)什么樣的功能。
4.1 返回真?zhèn)沃档姆椒?/h3>
注:pre- prefix前綴,suf- suffix后綴,alo-alone 單獨(dú)使用
| 位置 | 單詞 | 意義 | 例 |
|---|---|---|---|
| pre | is | 對(duì)象是否符合期待的狀態(tài) | isValid |
| pre | can | 對(duì)象能否執(zhí)行所期待的動(dòng)作 | canRemove |
| pre | should | 調(diào)用方執(zhí)行某個(gè)命令 或方法是好還是不好 應(yīng)不應(yīng)該, 或者說推薦還是不推薦 | shouldMigrate |
| pre | has | 對(duì)象是否持有 所期待的數(shù)據(jù)和屬性 | hasObservers |
| pre | needs | 調(diào)用方是否需要 執(zhí)行某個(gè)命令或方法 | needsMigrate |
4.2 用來檢查的方法
| 單詞 | 意義 | 例 |
|---|---|---|
| ensure | 檢查是否為期待的狀態(tài) 不是則拋出異常或返回error code | ensureCapacity |
| validate | 檢查是否為正確的狀態(tài) 不是則拋出異常或返回error code | validateInputs |
4.3 按需求才執(zhí)行的方法
| 位置 | 單詞 | 意義 | 例 |
|---|---|---|---|
| suf | IfNeeded | 需要的時(shí)候執(zhí)行 不需要?jiǎng)t什么都不做 | drawIfNeeded |
| pre | might | 同上 | mightCreate |
| pre | try | 嘗試執(zhí)行 失敗時(shí)拋出異常 或是返回errorcode | tryCreate |
| suf | OrDefault | 嘗試執(zhí)行 失敗時(shí)返回默認(rèn)值 | getOrDefault |
| suf | OrElse | 嘗試執(zhí)行 失敗時(shí)返回 實(shí)際參數(shù)中指定的值 | getOrElse |
| pre | force | 強(qiáng)制嘗試執(zhí)行 error拋出異常或是返回值 | forceCreate,? forceStop |
4.4 異步相關(guān)方法
| 位置 | 單詞 | 意義 | 例 |
|---|---|---|---|
| pre | blocking | 線程阻塞方法 | blockingGetUser |
| suf | InBackground | 執(zhí)行在后臺(tái)線程 | doInBackground |
| suf | Async | 異步方法 | sendAsync |
| suf | Sync | 同步方法 | sendSync |
pre | schedule | Job和Tas | schedule,? scheduleJob |
pre | post | 同上 | postJob |
pre | execute | 執(zhí)行異步 | execute, executeTask |
pre | start | 同上 | star, |
pre | cancel | 停止異步方法 | cance, |
pre | stop | 同上 | stop, stopJob |
4.5 回調(diào)方法
| 位置 | 單詞 | 意義 | 例 |
|---|---|---|---|
| pre | on | 事件發(fā)生時(shí)執(zhí)行 | onCompleted |
| pre | before | 事件發(fā)生前執(zhí)行 | beforeUpdate |
| pre | pre | 同上 | preUpdate |
| pre | will | 同上 | willUpdate |
| pre | after | 事件發(fā)生后執(zhí)行 | afterUpdate |
| pre | post | 同上 | postUpdate |
| pre | did | 同上 | didUpdate |
| pre | should | 確認(rèn)事件 是否可以執(zhí)行 | shouldUpdate |
4.6 操作對(duì)象生命周期的方法
| 單詞 | 意義 | 例 |
|---|---|---|
| initialize | 初始化或延遲初始化使用 | initialize |
| pause | 暫停 | onPause , pause |
| stop | 停止 | onStop, stop |
| abandon | 銷毀的替代 | abandon |
| destroy | 同上 | destroy |
| dispose | 同上 | dispose |
4.7 與集合操作相關(guān)的方法
| 單詞 | 意義 | 例 |
|---|---|---|
| contains | 是包含指定對(duì)象相同的對(duì)象 | contains |
| add | 添加 | addJob |
| append | 添加 | appendJob |
| insert | 插入到下標(biāo)n | insertJob |
| put | 添加與key對(duì)應(yīng)的元素 | putJob |
| remove | 移除元素 | removeJob |
| enqueue | 添加到隊(duì)列的最末位 | enqueueJob |
| dequeue | 從隊(duì)列中頭部取出并移除 | dequeueJob |
| push | 添加到棧頭 | pushJob |
| pop | 從棧頭取出并移除 | popJob |
| peek | 從棧頭取出但不移除 | peekJob |
| find | 尋找符合條件的某物 | findById |
4.8 與數(shù)據(jù)相關(guān)的方法
| 單詞 | 意義 | 例 |
|---|---|---|
| create | 新創(chuàng)建 | createAccount |
| new | 新創(chuàng)建 | newAccount |
| from | 從既有的某物新建 或是從其他的數(shù)據(jù)新建 | fromConfig |
| to | 轉(zhuǎn)換 | toString |
| update | 更新既有某物 | updateAccount |
| load | 讀取 | loadAccount |
| fetch | 遠(yuǎn)程讀取 | fetchAccount |
| delete | 刪除 | deleteAccount |
| remove | 刪除 | removeAccount |
| save | 保存 | saveAccount |
| store | 保存 | storeAccount |
| commit | 保存 | commitChange |
| apply | 保存或應(yīng)用 | applyChange |
| clear | 清除或是恢復(fù)到初始狀態(tài) | clearAll |
| reset | 清除或是恢復(fù)到初始狀態(tài) | resetAll |
4.9 成對(duì)出現(xiàn)的動(dòng)詞
| 單詞 | 意義 |
|---|---|
| get獲取 | set 設(shè)置 |
| add 增加 | remove 刪除 |
| create 創(chuàng)建 | destory 移除 |
| start 啟動(dòng) | stop 停止 |
| open 打開 | close 關(guān)閉 |
| read 讀取 | write 寫入 |
| load 載入 | save 保存 |
| create 創(chuàng)建 | destroy 銷毀 |
| begin 開始 | end 結(jié)束 |
| backup 備份 | restore 恢復(fù) |
| import 導(dǎo)入 | export 導(dǎo)出 |
| split 分割 | merge 合并 |
| inject 注入 | extract 提取 |
| attach 附著 | detach 脫離 |
| bind 綁定 | separate 分離 |
| view 查看 | browse 瀏覽 |
| edit 編輯 | modify 修改 |
| select 選取 | mark 標(biāo)記 |
| copy 復(fù)制 | paste 粘貼 |
| undo 撤銷 | redo 重做 |
| insert 插入 | delete 移除 |
| add 加入 | append 添加 |
| clean 清理 | clear 清除 |
| index 索引 | sort 排序 |
| find 查找 | search 搜索 |
| increase 增加 | decrease 減少 |
| play 播放 | pause 暫停 |
| launch 啟動(dòng) | run 運(yùn)行 |
| compile 編譯 | execute 執(zhí)行 |
| debug 調(diào)試 | trace 跟蹤 |
| observe 觀察 | listen 監(jiān)聽 |
| build 構(gòu)建 | publish 發(fā)布 |
| input 輸入 | output 輸出 |
| encode 編碼 | decode 解碼 |
| encrypt 加密 | decrypt 解密 |
| compress 壓縮 | decompress 解壓縮 |
| pack 打包 | unpack 解包 |
| parse 解析 | emit 生成 |
| connect 連接 | disconnect 斷開 |
| send 發(fā)送 | receive 接收 |
| download 下載 | upload 上傳 |
| refresh 刷新 | synchronize 同步 |
| update 更新 | revert 復(fù)原 |
| lock 鎖定 | unlock 解鎖 |
| check out 簽出 | check in 簽入 |
| submit 提交 | commit 交付 |
| push 推 | pull 拉 |
| expand 展開 | collapse 折疊 |
| begin 起始 | end 結(jié)束 |
| start 開始 | finish 完成 |
| enter 進(jìn)入 | exit 退出 |
| abort 放棄 | quit 離開 |
| obsolete 廢棄 | depreciate 廢舊 |
| collect 收集 | aggregate 聚集 |
五,變量&常量命名
5.1 變量命名
變量是指在程序運(yùn)行中可以改變其值的量,包括成員變量和局部變量。變量名由多單詞組成時(shí),第一個(gè)單詞的首字母小寫,其后單詞的首字母大寫,俗稱駱駝式命名法(也稱駝峰命名法),如 computedValues,index、變量命名時(shí),盡量簡短且能清楚的表達(dá)變量的作用,命名體現(xiàn)具體的業(yè)務(wù)含義即可。
變量名不應(yīng)以下劃線或美元符號(hào)開頭,盡管這在語法上是允許的。變量名應(yīng)簡短且富于描述。變量名的選用應(yīng)該易于記憶,即,能夠指出其用途。盡量避免單個(gè)字符的變量名,除非是一次性的臨時(shí)變量。pojo中的布爾變量,都不要加is(數(shù)據(jù)庫中的布爾字段全都要加 is_ 前綴)。
5.2 常量命名
常量命名CONSTANT_CASE,一般采用全部大寫(作為方法參數(shù)時(shí)除外),單詞間用下劃線分割。那么什么是常量呢?
常量是在作用域內(nèi)保持不變的值,一般使用final進(jìn)行修飾。一般分為三種,全局常量(public static final修飾),類內(nèi)常量(private static final 修飾)以及局部常量(方法內(nèi),或者參數(shù)中的常量),局部常量比較特殊,通常采用小駝峰命名即可。
/*** 一個(gè)demo** @author Jann Lee* @date 2019-12-07 00:25**/publicclassHelloWorld{/*** 局部常量(正例)*/publicstaticfinallong USER_MESSAGE_CACHE_EXPIRE_TIME =3600;/*** 局部常量(反例,命名不清晰)*/publicstaticfinallong MESSAGE_CACHE_TIME =3600;/*** 全局常量*/privatestaticfinalString ERROR_MESSAGE =" error message";/*** 成員變量*/privateint currentUserId;/*** 控制臺(tái)打印 {@code message} 信息** @param message 消息體,局部常量*/publicvoid sayHello(finalString message){System.out.println("Hello world!");}}
常量一般都有自己的業(yè)務(wù)含義,不要害怕長度過長而進(jìn)行省略或者縮寫。如,用戶消息緩存過期時(shí)間的表示,那種方式更佳清晰,交給你來評(píng)判。
通用命名規(guī)則
盡量不要使用拼音;杜絕拼音和英文混用。對(duì)于一些通用的表示或者難以用英文描述的可以采用拼音,一旦采用拼音就堅(jiān)決不能和英文混用。正例:BeiJing, HangZhou 反例:validateCanShu
命名過程中盡量不要出現(xiàn)特殊的字符,常量除外。
盡量不要和jdk或者框架中已存在的類重名,也不能使用java中的關(guān)鍵字命名。
妙用介詞,如for(可以用同音的4代替), to(可用同音的2代替), from, with,of等。如類名采用User4RedisDO,方法名getUserInfoFromRedis,convertJson2Map等。
六,代碼注解
6.1 注解的原則
好的命名增加代碼閱讀性,代碼的命名往往有嚴(yán)格的限制。而注解不同,程序員往往可以自由發(fā)揮,單并不意味著可以為所欲為之胡作非為。優(yōu)雅的注解通常要滿足三要素。
Nothing is strange 沒有注解的代碼對(duì)于閱讀者非常不友好,哪怕代碼寫的在清除,閱讀者至少從心理上會(huì)有抵觸,更何況代碼中往往有許多復(fù)雜的邏輯,所以一定要寫注解,不僅要記錄代碼的邏輯,還有說清楚修改的邏輯。
Less is more 從代碼維護(hù)角度來講,代碼中的注解一定是精華中的精華。合理清晰的命名能讓代碼易于理解,對(duì)于邏輯簡單且命名規(guī)范,能夠清楚表達(dá)代碼功能的代碼不需要注解。濫用注解會(huì)增加額外的負(fù)擔(dān),更何況大部分都是廢話。
// 根據(jù)id獲取信息【廢話注解】getMessageById(id)
Advance with the time 注解應(yīng)該隨著代碼的變動(dòng)而改變,注解表達(dá)的信息要與代碼中完全一致。通常情況下修改代碼后一定要修改注解。
6.2 注解格式
注解大體上可以分為兩種,一種是javadoc注解,另一種是簡單注解。javadoc注解可以生成JavaAPI為外部用戶提供有效的支持javadoc注解通常在使用IDEA,或者Eclipse等開發(fā)工具時(shí)都可以自動(dòng)生成,也支持自定義的注解模板,僅需要對(duì)對(duì)應(yīng)的字段進(jìn)行解釋。參與同一項(xiàng)目開發(fā)的同學(xué),盡量設(shè)置成相同的注解模板。
a. 包注解
包注解在工作中往往比較特殊,通過包注解可以快速知悉當(dāng)前包下代碼是用來實(shí)現(xiàn)哪些功能,強(qiáng)烈建議工作中加上,尤其是對(duì)于一些比較復(fù)雜的包,包注解一般在包的根目錄下,名稱統(tǒng)一為package-info.java。
/*** 落地也質(zhì)量檢測(cè)* 1. 用來解決什么問題* 對(duì)廣告主投放的廣告落地頁進(jìn)行性能檢測(cè),模擬不同的系統(tǒng),如Android,IOS等; 模擬不同的網(wǎng)絡(luò):2G,3G,4G,wifi等** 2. 如何實(shí)現(xiàn)* 基于chrome瀏覽器,用chromedriver驅(qū)動(dòng)瀏覽器,設(shè)置對(duì)應(yīng)的網(wǎng)絡(luò),OS參數(shù),獲取到瀏覽器返回結(jié)果。** 注意:網(wǎng)絡(luò)環(huán)境配置信息{@link cn.mycookies.landingpagecheck.meta.NetWorkSpeedEnum}目前使用是常規(guī)速度,可以根據(jù)實(shí)際情況進(jìn)行調(diào)整** @author cruder* @time 2019/12/7 20:3 下午*/package cn.mycookies.landingpagecheck;
b. 類注接
javadoc注解中,每個(gè)類都必須有注解。
/*** Copyright (C), 2019-2020, Jann balabala...** 類的介紹:這是一個(gè)用來做什么事情的類,有哪些功能,用到的技術(shù).....** @author 類創(chuàng)建者姓名 保持對(duì)齊* @date 創(chuàng)建日期 保持對(duì)齊* @version 版本號(hào) 保持對(duì)齊*/
c. 屬性注解
在每個(gè)屬性前面必須加上屬性注釋,通常有一下兩種形式,至于怎么選擇,你高興就好,不過一個(gè)項(xiàng)目中要保持統(tǒng)一。
/** 提示信息 */privateString userName;/*** 密碼*/privateString password;
d. 方法注釋
在每個(gè)方法前面必須加上方法注釋,對(duì)于方法中的每個(gè)參數(shù),以及返回值都要有說明。
/*** 方法的詳細(xì)說明,能干嘛,怎么實(shí)現(xiàn)的,注意事項(xiàng)...** @param xxx 參數(shù)1的使用說明, 能否為null* @return 返回結(jié)果的說明, 不同情況下會(huì)返回怎樣的結(jié)果* @throws 異常類型 注明從此類方法中拋出異常的說明*/
e. 構(gòu)造方法注釋
在每個(gè)構(gòu)造方法前面必須加上注釋,注釋模板如下:
/*** 構(gòu)造方法的詳細(xì)說明** @param xxx 參數(shù)1的使用說明, 能否為null* @throws 異常類型 注明從此類方法中拋出異常的說明*/
而簡單注解往往是需要工程師字節(jié)定義,在使用注解時(shí)應(yīng)該注意一下幾點(diǎn):
枚舉類的各個(gè)屬性值都要使用注解,枚舉可以理解為是常量,通常不會(huì)發(fā)生改變,通常會(huì)被在多個(gè)地方引用,對(duì)枚舉的修改和添加屬性通常會(huì)帶來很大的影響。
保持排版整潔,不要使用行尾注釋;雙斜杠和星號(hào)之后要用1個(gè)空格分隔。
int id =1;// 反例:不要使用行尾注釋//反例:換行符與注釋之間沒有縮進(jìn)int age =18;// 正例:姓名String name;/*** 1. 多行注釋** 2. 對(duì)于不同的邏輯說明,可以用空行分隔*/
總結(jié)
無論是命名和注解,他們的目的都是為了讓代碼和工程師進(jìn)行對(duì)話,增強(qiáng)代碼的可讀性,可維護(hù)性。優(yōu)秀的代碼往往能夠見名知意,注解往往是對(duì)命名的補(bǔ)充和完善。命名太南了!
參考文獻(xiàn):《碼出高效》
https://www.cnblogs.com/wangcp-2014/p/10215620.html
https://qiita.com/KeithYokoma/items/2193cf79ba76563e3db6
https://google.github.io/styleguide/javaguide.html#s2.1-file-name
推薦閱讀:
喜歡我可以給我設(shè)為星標(biāo)哦

好文章,我?在看?

