教妹學(xué)Java第15講:Java命名約定
同學(xué)們好啊,我是沉默王二。又到了《教妹學(xué) Java》的時(shí)間,我很開(kāi)心,你很期待,有木有?這是《教妹學(xué) Java》專(zhuān)欄的第 15 篇文章,我們來(lái)談?wù)劇癑ava 中的命名約定”。
強(qiáng)烈推薦:我在 GitHub 上發(fā)現(xiàn)了一個(gè)寶藏項(xiàng)目,里面收錄了 500+ 本電子書(shū),包含 Java、Spring、MySQL、設(shè)計(jì)模式、計(jì)算機(jī)網(wǎng)絡(luò)、計(jì)算機(jī)操作系統(tǒng)、數(shù)據(jù)結(jié)構(gòu)與算法、面試題等方面的電子書(shū),需要的小伙伴可以在后臺(tái)回復(fù)「Java」關(guān)鍵字獲取。
上一篇文章發(fā)表后,就有同學(xué)留言說(shuō)“妹妹大一就開(kāi)始學(xué)習(xí) Java 了,有點(diǎn)厲害啊。”我只能說(shuō),要對(duì)妹妹負(fù)責(zé),就必須得趁早,因?yàn)樯饨?jīng)有這么一句話:
人無(wú)我有,人有我好,人好我早,人多我早。
這句話用在生意上合適,用在學(xué)習(xí)上也是再合適不過(guò)了。當(dāng)別人都不懂一門(mén)新技術(shù)的時(shí)候,你懂,那么恭喜你,你已經(jīng)遙遙領(lǐng)先了;當(dāng)別人也懂了,你比他精通,那么你就是牛逼;當(dāng)別人也精通了,你比他精通的早,還是有優(yōu)勢(shì),對(duì)吧?
強(qiáng)調(diào)一下,《教妹學(xué) Java》面向的是零基礎(chǔ)的 Java 愛(ài)好者,我希望能幫助同學(xué)們輕松邁進(jìn)編程世界的大門(mén),為后續(xù)的深入學(xué)習(xí)打下堅(jiān)實(shí)的基礎(chǔ)。

“二哥,Java 中的命名約定都有哪些呢?”三妹的臉上泛著甜甜的笑容,她開(kāi)始對(duì)接下來(lái)要學(xué)習(xí)的內(nèi)容充滿期待了,這正是我感到欣慰的地方。
“對(duì)于我們中國(guó)人來(lái)說(shuō),名字也是有講究的,比如說(shuō)我叫沉默王二,你就叫沉默王三,哈哈。”我笑著對(duì)三妹說(shuō)。
命名約定決定我們使用什么樣的標(biāo)識(shí)符來(lái)命名包、類(lèi)、字段、方法等等,雖然這個(gè)規(guī)則不是強(qiáng)制的,可以遵守,也可以不遵守,但如果不遵守的話,就會(huì)帶來(lái)很多不必要的麻煩。
起個(gè)好的名字,就好像穿一件得體的衣服,呈現(xiàn)給人的用戶體驗(yàn)是完全不一樣的。
好的命名可以讓你的代碼更易讀,包括你自己和你的小伙伴,看一眼,不用想太多,就能明白代碼是干嘛的。
拿我這個(gè)筆名“沉默王二”來(lái)舉例吧,讀起來(lái)我就覺(jué)得朗朗上口,讀者看到這個(gè)筆名就知道我是一個(gè)什么樣的人——對(duì)不熟的人保持沉默,對(duì)熟的人妙語(yǔ)連珠,哈哈。
01、包(package)
包的命名應(yīng)該遵守以下規(guī)則:
應(yīng)該全部是小寫(xiě)字母
點(diǎn)分隔符之間有且僅有一個(gè)自然語(yǔ)義的英語(yǔ)單詞
包名統(tǒng)一使用單數(shù)形式,比如說(shuō)
com.itwanger.util不能是com.itwanger.utils在最新的 Java 編程規(guī)范中,要求開(kāi)發(fā)人員在自己定義的包名前加上唯一的前綴。由于互聯(lián)網(wǎng)上的域名是不會(huì)重復(fù)的,所以多數(shù)開(kāi)發(fā)人員采用自己公司(或者個(gè)人博客)在互聯(lián)網(wǎng)上的域名稱(chēng)作為包的唯一前綴。比如我文章中出現(xiàn)的代碼示例的包名就是
package com.itwanger。
02、類(lèi)(class)
類(lèi)的命名應(yīng)該遵守以下規(guī)則:
必須以大寫(xiě)字母開(kāi)頭
最好是一個(gè)名詞,比如說(shuō) System
類(lèi)名使用 UpperCamelCase(駝峰式命名)風(fēng)格
盡量不要省略成單詞的首字母,但以下情形例外:DO/BO/DTO/VO/AO/ PO / UID 等

另外,如果是抽象類(lèi)的話,使用 Abstract 或 Base 開(kāi)頭;如果是異常類(lèi)的話,使用 Exception 結(jié)尾;如果是測(cè)試類(lèi)的話,使用 Test 結(jié)尾。
03、接口(interface)
接口的命名應(yīng)該遵守以下規(guī)則:
必須以大寫(xiě)字母開(kāi)頭
最好是一個(gè)形容詞,比如說(shuō) Runnable
盡量不要省略成單詞的首字母
來(lái)看個(gè)例子:
interface?Printable?{}
接口和實(shí)現(xiàn)類(lèi)之間也有一些規(guī)則:
實(shí)現(xiàn)類(lèi)用 Impl 的后綴與接口區(qū)別,比如說(shuō) CacheServiceImpl 實(shí)現(xiàn) CacheService 接口
或者,AbstractTranslator 實(shí)現(xiàn) Translatable 接口
04、字段(field)和變量(variable)
字段和變量的命名應(yīng)該遵守以下規(guī)則:
必須以小寫(xiě)字母開(kāi)頭
可以包含多個(gè)單詞,第一個(gè)單詞的首字母小寫(xiě),其他的單詞首字母大寫(xiě),比如說(shuō)
firstName最好不要使用單個(gè)字符,比如說(shuō)
int a,除非是局部變量類(lèi)型與中括號(hào)緊挨相連來(lái)表示數(shù)組,比如說(shuō)
int[] arrayDemo,main 方法中字符串?dāng)?shù)組參數(shù)不應(yīng)該寫(xiě)成String args[]POJO 類(lèi)中的任何布爾類(lèi)型的變量,都不要加 is 前綴,否則部分框架解析會(huì)引起序列化錯(cuò)誤,我自己知道的有 fastjson
避免在子類(lèi)和父類(lèi)的成員變量之間、或者不同代碼塊的局部變量之間采用完全相同的命名,使可理解性降低。子類(lèi)、父類(lèi)成員變量名相同,即使是 public 類(lèi)型的變量也能夠通過(guò)編譯,另外,局部變量在同一方法內(nèi)的不同代碼塊中同名也是合法的,這些情況都要避免。
反例:
public?class?ConfusingName?{
????public?int?stock;
????//?非?setter/getter?的參數(shù)名稱(chēng),不允許與本類(lèi)成員變量同名
????public?void?get(String?alibaba)?{
????????if?(condition)?{
????????????final?int?money?=?666;
//?...
????????}
????????for?(int?i?=?0;?i?10;?i++)?{
//?在同一方法體中,不允許與其它代碼塊中的?money?命名相同?final?int?money?=?15978;
//?...
????????}
????}
}
class?Son?extends?ConfusingName?{
//?不允許與父類(lèi)的成員變量名稱(chēng)相同?public?int?stock;
}
05、常量(constant)
常量的命名應(yīng)該遵守以下規(guī)則:
應(yīng)該全部是大寫(xiě)字母
可以包含多個(gè)單詞,單詞之間使用“_”連接,比如說(shuō)
MAX_PRIORITY,力求語(yǔ)義表達(dá)完整清楚,不要嫌名字長(zhǎng)可以包含數(shù)字,但不能以數(shù)字開(kāi)頭
來(lái)看個(gè)例子:
static?final?int?MIN_AGE?=?18;??
06、方法(method)
方法的命名應(yīng)該遵守以下規(guī)則:
必須以小寫(xiě)字母開(kāi)頭
最好是一個(gè)動(dòng)詞,比如說(shuō)
print()可以包含多個(gè)單詞,第一個(gè)單詞的首字母小寫(xiě),其他的單詞首字母大寫(xiě),比如說(shuō)
actionPerformed()
來(lái)看個(gè)例子:
void?writeBook(){}
Service/DAO 層的方法命名規(guī)約:
獲取單個(gè)對(duì)象的方法用 get 做前綴
獲取多個(gè)對(duì)象的方法用 list 做前綴,復(fù)數(shù)結(jié)尾,如:listObjects
獲取統(tǒng)計(jì)值的方法用 count 做前綴
插入的方法用 save/insert 做前綴
刪除的方法用 remove/delete 做前綴
修改的方法用 update 做前綴
07、總結(jié)
除了以上這些規(guī)則以外,還有一些共同的規(guī)則需要遵守,比如說(shuō):
代碼中的命名均不能以下劃線或美元符號(hào)開(kāi)始,也不能以下劃線或美元符號(hào)結(jié)束。反例:
_name / __name / $name / name_ / name$ / name__所有編程相關(guān)的命名嚴(yán)禁使用拼音與英文混合的方式,更不允許直接使用中文的方式。反例:
DaZhePromotion [打折] / getPingfenByName() [評(píng)分] / String fw[福娃] / int 某變量 = 3代碼和注釋中都要避免使用任何語(yǔ)言的種族歧視性詞語(yǔ)。反例:
RIBENGUIZI / Asan / blackList / whiteList / slave方法名、參數(shù)名、成員變量、局部變量都統(tǒng)一使用 lowerCamelCase 風(fēng)格。
杜絕完全不規(guī)范的縮寫(xiě),避免望文不知義。反例:AbstractClass “縮寫(xiě)”成 AbsClass;condition “縮寫(xiě)”成 condi;Function 縮寫(xiě)”成 Fu,此類(lèi)隨意縮寫(xiě)嚴(yán)重降低了代碼的可閱讀性。
為了達(dá)到代碼自解釋的目標(biāo),任何自定義編程元素在命名時(shí),使用盡量完整的單詞組合來(lái)表達(dá)。
在常量與變量的命名時(shí),表示類(lèi)型的名詞放在詞尾,以提升辨識(shí)度。正例:
startTime / workQueue / nameList / TERMINATED_THREAD_COUNT如果模塊、接口、類(lèi)、方法使用了設(shè)計(jì)模式,在命名時(shí)需體現(xiàn)出具體模式。將設(shè)計(jì)模式體現(xiàn)在名字中,有利于閱讀者快速理解架構(gòu)設(shè)計(jì)理念。比如說(shuō):
public class OrderFactory;public class LoginProxy;public class ResourceObserver;枚舉類(lèi)名帶上 Enum 后綴,枚舉成員名稱(chēng)需要全大寫(xiě),單詞間用下劃線隔開(kāi)。枚舉其實(shí)就是特殊的常量類(lèi),且構(gòu)造方法被默認(rèn)強(qiáng)制是私有。比如說(shuō):
枚舉名字為 ProcessStatusEnum 的成員名稱(chēng):SUCCESS / UNKNOWN_REASON。
“好了,三妹,關(guān)于 Java 中的命名約定就先說(shuō)這么多吧,你平常在寫(xiě)代碼的時(shí)候注意一下,養(yǎng)成好習(xí)慣。”轉(zhuǎn)動(dòng)了一下僵硬的脖子后,我對(duì)三妹說(shuō)。
“好的,二哥,你辛苦了,原來(lái)命名約定還有這么多說(shuō)法,真的是你知道的越多,你不知道的越多啊。”
這是《教妹學(xué) Java》專(zhuān)欄的第 15 篇文章,能看到這里的小伙伴都是最帥的,最美的,升職加薪就是你了?。

寫(xiě)這個(gè)專(zhuān)欄的初衷就是為了幫助那些零基礎(chǔ)學(xué) Java,或者自學(xué) Java 感覺(jué)特別痛苦,特別難入門(mén)的小伙伴。
另外,我還創(chuàng)建了一些「技術(shù)交流群」,群里氛圍很不錯(cuò),有不少小伙伴會(huì)分享一些校招或者社招經(jīng)驗(yàn),更重要的是,群里時(shí)不時(shí)會(huì)有「紅包」等福利,當(dāng)然,群里不允許任何形式的廣告。掃描下方的二維碼,回復(fù)「加群」即可。
示例代碼已經(jīng)同步到 GitHub,地址為 github.com/itwanger,也可以點(diǎn)擊閱讀原文進(jìn)行跳轉(zhuǎn),歡迎 star。
