1 簡(jiǎn)介
這份是Google Java編程風(fēng)格規(guī)范文檔莫其。當(dāng)且僅當(dāng)一個(gè)Java源文件符合此文檔中的規(guī)則時(shí),我們才認(rèn)為它符合Google的Java編程風(fēng)格冬耿。
與其它的編程風(fēng)格指南一樣追葡,這里所討論的不僅僅是編碼格式美不美觀的問(wèn)題贵扰,同時(shí)也討論一些約定及編碼標(biāo)準(zhǔn)。然而嗦锐,這份文檔主要側(cè)重于我們所普遍遵循的規(guī)則顶猜,對(duì)于那些不是明確強(qiáng)制要求的,我們盡量避免提供意見(jiàn)粤剧。
1.1 術(shù)語(yǔ)說(shuō)明
在本文檔中歇竟,除非另有說(shuō)明:
- 術(shù)語(yǔ)
class
可表示一個(gè)普通類、枚舉類俊扳、接口或是注解類型(@interface)途蒋。 - 術(shù)語(yǔ)
member
(類的成員)可表示內(nèi)部類、變量馋记、方法或是構(gòu)造函數(shù)号坡;即除了初始化代碼塊與注釋以外的類的所有頂級(jí)內(nèi)容。 - 術(shù)語(yǔ)
comment
通常用于表示實(shí)現(xiàn)的注釋(implementation comments)梯醒,我們不使用“documentation comments”宽堆,而是用“Javadoc”。
其他的“術(shù)語(yǔ)說(shuō)明”則會(huì)在后面的文檔中偶爾出現(xiàn)茸习。
1.2 指南說(shuō)明
本文檔中的示例代碼是非規(guī)范的畜隶。也就是說(shuō),雖然示例遵循Google Style号胚,但其并不代表這就是體現(xiàn)代碼優(yōu)雅的唯一方式籽慢。示例中的格式選擇不應(yīng)該被強(qiáng)制定為規(guī)則。
2 源文件基礎(chǔ)
2.1 文件名
源文件以其頂級(jí)類的類名來(lái)命名猫胁,大小寫敏感箱亿,文件擴(kuò)展名為.java
。
2.2 文件編碼:UTF-8
源文件編碼格式為UTF-8弃秆。
2.3 特殊字符
2.3.1 空白字符
除了行結(jié)束符序列届惋,ASCII水平空格字符(0x20髓帽,即空格)是源文件中唯一允許出現(xiàn)的空白字符,這意味著:
- 所有其它字符串中的空白字符都要進(jìn)行轉(zhuǎn)義脑豹。
- 制表符不用于縮進(jìn)郑藏。
2.3.2 特殊轉(zhuǎn)義序列
對(duì)于具有特殊轉(zhuǎn)義序列的任何字符(\b、 \t瘩欺、\n必盖、\f、\r俱饿、"筑悴、'及\),我們使用它的轉(zhuǎn)義序列稍途,而不是相應(yīng)的八進(jìn)制(比如\012
)或Unicode(比如\u000a
)轉(zhuǎn)義阁吝。
2.3.3 非ASCII字符
對(duì)于剩余的非ASCII字符,是使用實(shí)際的Unicode字符(比如∞
)械拍,還是使用等價(jià)的Unicode轉(zhuǎn)義符(比如\u221e
)突勇,取決于哪個(gè)能讓代碼更易于閱讀和理解。
提示:在使用Unicode轉(zhuǎn)義符或是一些實(shí)際的Unicode字符時(shí)坷虑,建議做些注釋給出解釋甲馋,這有助于別人閱讀和理解。
例如:
示例 | 討論區(qū) |
---|---|
String unitAbbrev = "μs"; | 最佳迄损,即使沒(méi)有注釋也非常清晰定躏。 |
String unitAbbrev = "\u03bcs"; // "μs" | 允許,但沒(méi)有理由要這樣做芹敌。 |
String unitAbbrev = "\u03bcs"; // Greek letter mu, "s" | 允許痊远,但這樣做顯得笨拙還容易出錯(cuò)。 |
String unitAbbrev = "\u03bcs"; | 很糟氏捞,讀者根本看不出這是什么碧聪。 |
return '\ufeff' + content; // byte order mark | 很好,對(duì)于非打印字符液茎,使用轉(zhuǎn)義逞姿,并在必要時(shí)寫上注釋。 |
提示:永遠(yuǎn)不要因?yàn)楹ε履承┏绦蚩赡軣o(wú)法正確處理非ASCII字符而讓你的代碼可讀性變差捆等。當(dāng)程序無(wú)法正確處理非ASCII字符時(shí)滞造,它自然無(wú)法正確運(yùn)行,然后你就必須需修復(fù)它了栋烤。
3 源文件結(jié)構(gòu)
一個(gè)源文件按順序包含:
- 許可證或版權(quán)信息(如需)
- package語(yǔ)句
- import語(yǔ)句
- 有且僅有一個(gè)的頂級(jí)類
以上每個(gè)部分之間用一個(gè)空行隔開(kāi)谒养。
3.1 許可證或版權(quán)信息(如需)
如果一個(gè)文件包含許可證或版權(quán)信息,那么它應(yīng)當(dāng)被放在文件最前面班缎。
3.2 package語(yǔ)句
package語(yǔ)句不換行蝴光,列限制(章節(jié)4.4)并不適用于package語(yǔ)句。
3.3 import語(yǔ)句
3.3.1 import不要使用通配符
不使用靜態(tài)或其他方式的通配符導(dǎo)入达址。
3.3.2 不要換行
import語(yǔ)句不換行蔑祟,列限制(章節(jié)4.4)并不適用于import語(yǔ)句。
3.3.3 順序和間距
import順序如下:
- 所有的靜態(tài)import獨(dú)立成組沉唠。
- 所有的非靜態(tài)import獨(dú)立成組疆虚。
如果存在靜態(tài)和非靜態(tài)導(dǎo)入,則單個(gè)空白行分隔兩個(gè)塊满葛。 import語(yǔ)句之間沒(méi)有其他空行径簿。
在每個(gè)塊中,導(dǎo)入的名稱以ASCII排序順序顯示嘀韧。(注意:這與以ASCII排序順序的import語(yǔ)句不同篇亭,因?yàn)椤?”排在“;”前面。)
3.3.4 不能用于靜態(tài)導(dǎo)入的類
靜態(tài)導(dǎo)入不能用于靜態(tài)內(nèi)部類锄贷。它們以普通導(dǎo)入方式導(dǎo)入译蒂。
3.4 類聲明
3.4.1 有且僅有一個(gè)頂級(jí)類
每個(gè)頂級(jí)類都駐留在自己的源文件中。
3.4.2 類成員順序
類的成員順序?qū)σ讓W(xué)性有很大的影響谊却,但這也不存在唯一的通用法則柔昼。不同的類對(duì)成員的排序可能是不同的。
最重要的一點(diǎn)炎辨,每個(gè)類應(yīng)該以某種邏輯去排序它的成員捕透,維護(hù)者應(yīng)該要能解釋這種排序邏輯。比如碴萧,新的方法不能總是習(xí)慣性地添加到類的結(jié)尾乙嘀,因?yàn)檫@樣就是按時(shí)間順序而非某種邏輯來(lái)排序的。
3.4.2.1 重載:永遠(yuǎn)不要分割
當(dāng)一個(gè)類有多個(gè)構(gòu)造函數(shù)破喻,或是多個(gè)同名方法時(shí)乒躺,這些函數(shù)/方法應(yīng)該按順序出現(xiàn)在一起,中間不要放進(jìn)其它函數(shù)/方法低缩。
4 格式化
術(shù)語(yǔ)說(shuō)明:塊狀結(jié)構(gòu)(block-like construct)指的是一個(gè)類嘉冒,方法或構(gòu)造函數(shù)的主體。需要注意的是(章節(jié)4.8.3.1)咆繁,數(shù)組初始化中的初始值可被選擇性地視為塊狀結(jié)構(gòu)讳推。
4.1 大括號(hào)
4.1.1 使用大括號(hào)(即使是可選的)
大括號(hào)與if、else玩般、for银觅、do及while語(yǔ)句一起使用,即使只有一條語(yǔ)句或是空坏为,也應(yīng)該把大括號(hào)寫上究驴。
4.1.2 非空塊:K & R 風(fēng)格
對(duì)于非空塊和塊狀結(jié)構(gòu)镊绪,大括號(hào)遵循 Kernighan 和 Ritchie 風(fēng)格(Egyptian brackets):
- 左大括號(hào)前不換行
- 左大括號(hào)后換行
- 右大括號(hào)前換行
- 只有右大括號(hào)是一個(gè)語(yǔ)句、函數(shù)體或類的終止時(shí)洒忧,右大括號(hào)后才換行蝴韭。例如,如果后面跟著else或逗號(hào)熙侍,那么右大括號(hào)后面不換行榄鉴。
示例:
return () -> {
while (condition()) {
method();
}
};
return new MyClass() {
@Override public void method() {
if (condition()) {
try {
something();
} catch (ProblemException e) {
recover();
}
} else if (otherCondition()) {
somethingElse();
} else {
lastThing();
}
}
};
章節(jié)4.8.1給出了enum類的一些例外。
4.1.3 空塊:可以用簡(jiǎn)潔版本
一個(gè)空的塊狀結(jié)構(gòu)里什么也不包含蛉抓,大括號(hào)可以簡(jiǎn)潔地寫成{}庆尘,不需要換行。例外:如果它是一個(gè)多塊語(yǔ)句的一部分(if/else 或 try/catch/finally) 巷送,即使大括號(hào)內(nèi)沒(méi)內(nèi)容驶忌,右大括號(hào)也要換行。
示例:
// 這是可以接受的
void doNothing() {}
// 這是同樣可以接受的
void doNothingElse() {
}
// 這是不可接受的: 多塊語(yǔ)句中沒(méi)有簡(jiǎn)明的空塊
try {
doSomething();
} catch (Exception e) {}
4.2 塊縮進(jìn):4個(gè)空格
每次打開(kāi)新的塊或塊狀構(gòu)造時(shí)笑跛,縮進(jìn)增加4個(gè)空格位岔。當(dāng)塊結(jié)束時(shí),縮進(jìn)返回到上一縮進(jìn)級(jí)別堡牡∈闾В縮進(jìn)級(jí)別適用于整個(gè)塊中的代碼和注釋。(詳見(jiàn)章節(jié)4.1.2中的代碼示例)
4.3 一行一個(gè)語(yǔ)句
每個(gè)語(yǔ)句后要換行晤柄。
4.4 列限制:100
Java代碼的列限制為100個(gè)字符擦剑。“字符”表示任何Unicode碼位芥颈。除以下所述外惠勒,任何超出此限制的行都必須換行,如第4.5節(jié)“換行”中所述爬坑。
每個(gè)Unicode碼位都算作一個(gè)字符纠屋,即使其顯示寬度更大或更小。例如盾计,如果使用全角字符售担,則可以選擇在此規(guī)則嚴(yán)格要求的位置之前換行。
例外:
- 不可能滿足列限制的行(例如署辉,Javadoc中的一個(gè)長(zhǎng)URL族铆,或是一個(gè)長(zhǎng)的JSNI方法參考)。
- package和import語(yǔ)句(見(jiàn)章節(jié)3.2和章節(jié)3.3)哭尝。
- 注釋中那些可能被剪切并粘貼到shell中的命令行哥攘。
4.5 自動(dòng)換行
術(shù)語(yǔ)說(shuō)明:將原本可以合法占用一行的代碼分成多行時(shí),我們稱之為自動(dòng)換行(line-wrapping)。
我們并沒(méi)有全面逝淹、確定性的準(zhǔn)則來(lái)決定在每一種情況下如何自動(dòng)換行耕姊。很多時(shí)候,對(duì)于同一段代碼會(huì)有好幾種有效的自動(dòng)換行方式栅葡。
說(shuō)明:雖然自動(dòng)換行的典型原因是為了避免溢出列限制茉兰,但事實(shí)上符合列限制的代碼也可以換行,這由代碼作者自行決定妥畏。
提示:通過(guò)提取方法或局部變量可以解決不得不換行的問(wèn)題。
4.5.1 從哪里斷開(kāi)
自動(dòng)換行的基本準(zhǔn)則是:更傾向于在更高的語(yǔ)法級(jí)別處斷開(kāi)安吁。如:
- 如果在非賦值運(yùn)算符處斷開(kāi)醉蚁,那么在該符號(hào)前斷開(kāi)。(注意:這一點(diǎn)與Google其它語(yǔ)言的編程風(fēng)格不同鬼店,如C++和JavaScript网棍。)這條規(guī)則也適用于以下"類運(yùn)算符"符號(hào):
- 點(diǎn)分隔符(.)
- 一個(gè)方法引用的兩個(gè)冒號(hào)(::)
- 類型界限中的"&"(<T extends Foo & Bar>)
- 捕獲塊中的管道符號(hào)(catch (FooException | BarException e))。
- 如果在賦值運(yùn)算符處斷開(kāi)妇智,通常在該符號(hào)后斷開(kāi)滥玷,但是在符號(hào)之前也是可以接受的。
- 這條規(guī)則也適用于foreach語(yǔ)句中的冒號(hào)巍棱。
- 方法名或構(gòu)造函數(shù)名與左括號(hào)(()留在同一行惑畴。
- 逗號(hào)(,)與其前面的內(nèi)容留在同一行。
- 在Lambda表達(dá)式中航徙,一行從不會(huì)被斷開(kāi)如贷,除了如果Lambda表達(dá)式的主體由單個(gè)非支持表達(dá)式組成,則可能會(huì)在箭頭之后立即出現(xiàn)斷開(kāi)到踏。示例:
MyLambda<String, Long, Object> lambda =
(String label, Long value, Object obj) -> {
...
};
Predicate<String> predicate = str ->
longExpressionInvolving(str);
說(shuō)明:自動(dòng)換行的主要目的是為了使代碼更為清晰杠袱,而對(duì)于行數(shù)少的代碼則是不需要的。
4.5.2 自動(dòng)換行時(shí)縮進(jìn)至少+4個(gè)空格
自動(dòng)換行時(shí)窝稿,第一行后面的每一行(每個(gè)連續(xù)行)從原始行縮進(jìn)至少增加4個(gè)空格楣富。
當(dāng)存在連續(xù)自動(dòng)換行時(shí),縮進(jìn)可能會(huì)多縮進(jìn)不只4個(gè)空格(語(yǔ)法元素存在多級(jí)時(shí))伴榔。一般而言纹蝴,兩個(gè)連續(xù)行使用相同的縮進(jìn)當(dāng)且僅當(dāng)它們開(kāi)始于同級(jí)語(yǔ)法元素。
章節(jié)4.6.3水平對(duì)齊一節(jié)中指出踪少,不鼓勵(lì)使用可變數(shù)目的空格來(lái)對(duì)齊前面行的符號(hào)骗灶。
4.6 空白
4.6.1 垂直空白
以下情況需要使用一個(gè)空行:
- 類內(nèi)連續(xù)的成員或初始化程序之間:字段,構(gòu)造函數(shù)秉馏,方法耙旦,嵌套類,靜態(tài)初始化塊,實(shí)例初始化塊免都。
- 例外:兩個(gè)連續(xù)字段之間的空行(在它們之間沒(méi)有其他代碼)是可選的锉罐。這樣的空白行根據(jù)需要用于創(chuàng)建字段的邏輯分組。
- 例外:枚舉常量之間的空行绕娘,章節(jié)4.8.1將介紹脓规。
- 據(jù)本文檔其他部分的要求(例如第3節(jié):源文件結(jié)構(gòu)和第3.3節(jié):Import語(yǔ)句)。
單個(gè)空白行也可能出現(xiàn)在提高可讀性的任何地方险领,例如在將代碼組織為邏輯小節(jié)的語(yǔ)句之間侨舆。不鼓勵(lì)也不鼓勵(lì)在類的第一個(gè)成員或初始化程序之前,或在最后一個(gè)成員或初始化程序之后的空白行绢陌。
多個(gè)連續(xù)的空行是允許的挨下,但沒(méi)有必要這樣做(也不鼓勵(lì)這樣做)。
4.6.2 水平空白
除了語(yǔ)言需求和其它規(guī)則脐湾,并且除了文字臭笆,注釋和Javadoc用到單個(gè)空格,單個(gè)ASCII空格僅出現(xiàn)在以下幾個(gè)地方:
- 分隔任何保留字(如:if秤掌、for及catch)與緊隨其后的左括號(hào)(()愁铺。
- 分隔任何保留字(如:else或catch)與其前面的右大括號(hào)(})。
- 在任何左大括號(hào)前({)闻鉴,兩個(gè)例外:
- @SomeAnnotation({a, b})(不使用空格)
- String[][] x = {{"foo"}};(兩個(gè)大括號(hào)之間無(wú)空格)
- 在任何二元或三元運(yùn)算符的兩側(cè)茵乱。這也適用于以下"類運(yùn)算符"符號(hào):
- 類型界限中的&符:<T extends Foo & Bar>
- catch塊中的管道符號(hào):catch (FooException | BarException e)
- foreach語(yǔ)句中的冒號(hào)(:)
- Lambda表達(dá)式中的箭頭: (String str) -> str.length()
但不適用于一下情況: - 方法引用的兩個(gè)冒號(hào)(::),如Object::toString
- 點(diǎn)分隔符(.)孟岛,如object.toString()
- 在, : ;及右括號(hào)())后
- 如果在一條語(yǔ)句后做注釋似将,則雙斜杠(//)兩邊都要空格。這里可以允許多個(gè)空格蚀苛,但沒(méi)有必要在验。
- 類型和變量之間:List<String> list
- 在數(shù)組初始值設(shè)定符的兩個(gè)大括號(hào)內(nèi)可選
- new int[] {5, 6}與new int[] { 5, 6 }都可行
- 在類型注釋和[]或...之間
此規(guī)則不應(yīng)理解為在行的開(kāi)始或結(jié)束處要求或禁止額外的空格; 它只涉及行的內(nèi)部空格。
4.6.3 水平對(duì)齊:不做要求
術(shù)語(yǔ)說(shuō)明:水平對(duì)齊指的是通過(guò)增加可變數(shù)量的空格來(lái)使某一行的字符與上一行的相應(yīng)字符對(duì)齊堵未。
這是允許的腋舌,但Google編程風(fēng)格對(duì)此不做要求。即使對(duì)于已經(jīng)使用水平對(duì)齊的代碼渗蟹,我們也不需要去保持這種風(fēng)格块饺。
以下示例先展示未對(duì)齊的代碼和對(duì)齊的代碼:
private int x; // this is fine
private Color color; // this too
private int x; // permitted, but future edits
private Color color; // may leave it unaligned
說(shuō)明:對(duì)齊可增加代碼可讀性,但它為日后的維護(hù)帶來(lái)問(wèn)題雌芽∈诩瑁考慮未來(lái)某個(gè)時(shí)候,我們需要修改一堆對(duì)齊的代碼中的一行世落。這可能導(dǎo)致原本很漂亮的對(duì)齊代碼變得錯(cuò)位淮腾。很可能它會(huì)提示你調(diào)整周圍代碼的空白來(lái)使這一堆代碼重新水平對(duì)齊(比如程序員想保持這種水平對(duì)齊的風(fēng)格)。這就會(huì)讓你做許多的無(wú)用功,增加了reviewer的工作并且可能導(dǎo)致更多的合并沖突谷朝。
4.7 用小括號(hào)來(lái)限定組:推薦
除非作者和reviewer都認(rèn)為去掉小括號(hào)也不會(huì)使代碼被誤解洲押,或是去掉小括號(hào)能讓代碼更易于閱讀,否則我們不應(yīng)該去掉小括號(hào)圆凰。我們沒(méi)有理由假設(shè)讀者能記住整個(gè)Java運(yùn)算符優(yōu)先級(jí)表杈帐。
4.8 具體結(jié)構(gòu)
4.8.1 枚舉類
枚舉常量間用逗號(hào)隔開(kāi),換行可選专钉。還允許附加空行(通常只有一個(gè))挑童。這是一個(gè)樣例:
private enum Answer {
YES {
@Override public String toString() {
return "yes";
}
},
NO,
MAYBE
}
沒(méi)有方法和文檔的枚舉類可寫成數(shù)組初始化的格式(詳見(jiàn)章節(jié)4.8.3.1)。
private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }
由于枚舉類也是一個(gè)類跃须,因此所有適用于其它類的格式規(guī)則也適用于枚舉類站叼。
4.8.2 變量聲明
4.8.2.1 每次只聲明一個(gè)變量
不要使用組合聲明,如int a, b;回怜。
例外:for循環(huán)的頭中可以使用多個(gè)變量聲明大年。
4.8.2.2 需要時(shí)再聲明
不要在一個(gè)代碼塊的開(kāi)頭把局部變量一次性都聲明了换薄,而是在第一次需要使用它時(shí)才聲明玉雾。局部變量在聲明時(shí)最好就進(jìn)行初始化,或者聲明后盡快進(jìn)行初始化轻要。
4.8.3 數(shù)組
4.8.3.1 數(shù)組初始化:可寫成塊狀結(jié)構(gòu)
數(shù)組初始化可以寫成塊狀結(jié)構(gòu)复旬,比如,下面的寫法都是可行的:
new int[] {
0, 1, 2, 3
}
new int[] {
0,
1,
2,
3
}
new int[] {
0, 1,
2, 3
}
new int[]
{0, 1, 2, 3}
4.8.3.2 非C風(fēng)格的數(shù)組聲明
中括號(hào)是類型的一部分:String[] args冲泥, 而非 String args[]驹碍。
4.8.4 switch語(yǔ)句
術(shù)語(yǔ)說(shuō)明:switch塊的大括號(hào)內(nèi)是一個(gè)或多個(gè)語(yǔ)句組。每個(gè)語(yǔ)句組包含一個(gè)或多個(gè)switch標(biāo)簽(case FOO:或default:)凡恍,后面跟著一條或多條語(yǔ)句(最后一個(gè)語(yǔ)句組后面沒(méi)有語(yǔ)句或者跟著多條語(yǔ)句)志秃。
4.8.4.1 縮進(jìn)
與其它塊狀結(jié)構(gòu)一致,switch塊中的內(nèi)容縮進(jìn)2個(gè)空格嚼酝。
在一個(gè)switch標(biāo)簽之后浮还,有一個(gè)換行符,縮進(jìn)級(jí)別增加2闽巩,就像一個(gè)塊被打開(kāi)一樣钧舌。緊接著的switch標(biāo)簽返回到上一個(gè)縮進(jìn)級(jí)別,就好像塊已關(guān)閉一樣涎跨。
4.8.4.2 Fall-through:注釋
在一個(gè)switch塊內(nèi)洼冻,每個(gè)語(yǔ)句組要么通過(guò)break、continue隅很、return或拋出異常來(lái)終止撞牢,要么通過(guò)一條注釋來(lái)說(shuō)明程序?qū)⒗^續(xù)執(zhí)行到下一個(gè)語(yǔ)句組,任何能表達(dá)這個(gè)意思的注釋都是可行的(典型的是用 // fall through)。這個(gè)特殊的注釋并不需要在最后一個(gè)語(yǔ)句組中出現(xiàn)普泡。示例:
switch (input) {
case 1:
case 2:
prepareOneOrTwo();
// fall through
case 3:
handleOneTwoOrThree();
break;
default:
handleLargeNumber(input);
}
注意播掷,在case 1后面不需要注釋,只有在語(yǔ)句組的末尾需要撼班。
4.8.4.3 default的情況要寫出來(lái)
每個(gè)switch語(yǔ)句包括一個(gè)default語(yǔ)句組歧匈,即使它不包含代碼。
例外:enum類型的switch語(yǔ)句可以省略default語(yǔ)句組砰嘁,如果它包括覆蓋該類型的所有可能值的顯式情況件炉。這使IDE或其他靜態(tài)分析工具能夠在錯(cuò)過(guò)任何情況時(shí)發(fā)出警告。
4.8.5 注解
注解緊跟在文檔塊后面矮湘,應(yīng)用于類斟冕、方法和構(gòu)造函數(shù),一個(gè)注解獨(dú)占一行缅阳。這些換行不屬于自動(dòng)換行(章節(jié)4.5磕蛇,自動(dòng)換行),因此縮進(jìn)級(jí)別不變十办。示例:
@Override
@Nullable
public String getNameIfPresent() { ... }
例外: 單個(gè)的注解可以和簽名的第一行出現(xiàn)在同一行秀撇。如:
@Override public int hashCode() { ... }
應(yīng)用于字段的注解緊隨文檔塊出現(xiàn),應(yīng)用于字段的多個(gè)注解允許與字段出現(xiàn)在同一行向族。如:
@Partial @Mock DataLoader loader;
參數(shù)和局部變量注解沒(méi)有特定規(guī)則呵燕。
4.8.6 注釋
本節(jié)討論實(shí)現(xiàn)注釋。Javadoc在章節(jié)7 Javadoc中單獨(dú)講解件相。
任何換行符之前可以有任意空格再扭,然后是實(shí)現(xiàn)注釋。這樣的注釋使該行非空白夜矗。
4.8.6.1 塊注釋風(fēng)格
塊注釋與其周圍的代碼在同一縮進(jìn)級(jí)別泛范。它們可以是/* ... */
風(fēng)格,也可以是// ...
風(fēng)格紊撕。對(duì)于多行的/* ... */
注釋罢荡,后續(xù)行必須以開(kāi)始, 并且與前一行的對(duì)齊逛揩。
/*
* This is
* okay.
*/
// And so
// is this.
/* Or you can
* even do this. */
注釋不要包含在標(biāo)有星號(hào)或其他字符的框中柠傍。
提示:當(dāng)編寫多行注釋時(shí),如果您希望自動(dòng)代碼格式化程序在必要時(shí)重新?lián)Q行(段落樣式)辩稽,請(qǐng)使用
/* ... */
樣式惧笛。大多數(shù)格式化程序不會(huì)在// ...
樣式注釋塊中重新?lián)Q行。
4.8.7 修飾符
類和成員的修飾符如果存在逞泄,則按Java語(yǔ)言規(guī)范中推薦的順序出現(xiàn)患整。
public protected private abstract default static final transient volatile synchronized native strictfp
4.8.8 數(shù)字字面量
long數(shù)值使用大寫L后綴拜效,而非小寫(以避免與數(shù)字1混淆)。例如各谚,3000000000L而不是3000000000l紧憾。
5 命名
5.1 對(duì)所有標(biāo)識(shí)符都通用的規(guī)則
標(biāo)識(shí)符只能使用ASCII字母和數(shù)字,因此每個(gè)有效的標(biāo)識(shí)符名稱都能匹配正則表達(dá)式\w+昌渤。
在Google Style中赴穗,特殊的前綴或后綴不被使用。例如膀息,name_
般眉、mName
、s_name
和kName
潜支。
5.2 標(biāo)識(shí)符類型的規(guī)則
5.2.1 包名
包名稱都是小寫甸赃,連續(xù)的單詞連接在一起(無(wú)下劃線)。如com.example.deepspace
而非com.example.deepSpace
或com.example.deep_space
冗酿。
5.2.2 類名
類名都以UpperCamelCase風(fēng)格編寫埠对。
類名通常是名詞或名詞短語(yǔ)(如:Character或ImmutableList),接口名稱通常也是名詞或名詞短語(yǔ)(如List)裁替,但有時(shí)可能是形容詞或形容詞短語(yǔ)(如Readable)项玛。
現(xiàn)在還沒(méi)有特定的規(guī)則或行之有效的約定來(lái)命名注解類型。
測(cè)試類從它們正在測(cè)試的類的名稱開(kāi)始命名胯究,并以Test結(jié)束稍计。例如躁绸,HashTest或HashIntegrationTest裕循。
5.2.3 方法名
方法名都以lowerCamelCase風(fēng)格編寫。
方法名稱通常是動(dòng)詞或動(dòng)詞短語(yǔ)净刮。例如剥哑,sendMessage或stop。
下劃線可能出現(xiàn)在JUnit測(cè)試方法名稱中淹父,用以分隔名稱的邏輯株婴。一個(gè)典型的模式是test<MethodUnderTest>_<state>,例如testPop_emptyStack暑认。目前尚未出現(xiàn)給測(cè)試方法命名的標(biāo)準(zhǔn)命名準(zhǔn)則困介。
5.2.4 常量名
常量名命名模式為CONSTANT_CASE,全部字母大寫蘸际,用下劃線分隔單詞座哩。那到底什么算是一個(gè)常量?
常數(shù)是靜態(tài)final字段粮彤,其內(nèi)容是不可變的根穷,并且其方法沒(méi)有可檢測(cè)的函數(shù)副作用姜骡。這包括基元、字符串屿良、不可變類型和不可變類型的不可變集合圈澈。如果任何實(shí)例的觀測(cè)狀態(tài)可以改變,它就不是一個(gè)常量尘惧。靜態(tài)final字段不一定都是常量康栈。例如:
// Constants
static final int NUMBER = 5;
static final ImmutableList<String> NAMES = ImmutableList.of("Ed", "Ann");
static final ImmutableMap<String, Integer> AGES = ImmutableMap.of("Ed", 35, "Ann", 32);
static final Joiner COMMA_JOINER = Joiner.on(','); // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
enum SomeEnum { ENUM_CONSTANT }
// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final Set<String> mutableCollection = new HashSet<String>();
static final ImmutableSet<SomeMutableType> mutableElements = ImmutableSet.of(mutable);
static final ImmutableMap<String, SomeMutableType> mutableValues =
ImmutableMap.of("Ed", mutableInstance, "Ann", mutableInstance2);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};
這些名字通常是名詞或名詞短語(yǔ)。
5.2.5 非常量字段名
非常量字段名(靜態(tài)或其他)以lowerCamelCase風(fēng)格編寫喷橙。
這些名稱通常是名詞或名詞短語(yǔ)谅将。例如,computedValues或index重慢。
5.2.6 參數(shù)名
參數(shù)名以lowerCamelCase風(fēng)格編寫饥臂。
應(yīng)該避免公共方法中的單字符參數(shù)名稱。
5.2.7 局部變量名
局部變量名以lowerCamelCase風(fēng)格編寫似踱。
即使局部變量是final和不可改變的隅熙,也不應(yīng)該把它示為常量,自然也不能用常量的規(guī)則去命名它核芽。
5.2.8 類型變量名
類型變量可用以下兩種風(fēng)格之一進(jìn)行命名:
- 單個(gè)的大寫字母囚戚,后面可以跟一個(gè)數(shù)字(如:E、T轧简、X驰坊、T2)。
- 以類命名方式(章節(jié)5.2.2)哮独,后面加個(gè)大寫的T(如:RequestT拳芙、FooBarT)。
5.3 CamelCase:定義
有時(shí)不止一種合理的方式可以將短語(yǔ)轉(zhuǎn)換為CamelCase模式皮璧,例如首字母縮略詞或不尋常的結(jié)構(gòu)舟扎,如“IPv6”或“iOS”。為了提高可預(yù)測(cè)性悴务,Google Style指定(盡量)使用以下確定性方案睹限。
從名稱的文本形式開(kāi)始:
- 將短語(yǔ)轉(zhuǎn)換為純ASCII并刪除任何省略號(hào)。例如:“Müller's algorithm”可改為“Muellers algorithm”讯檐。
- 根據(jù)空格和任何有的標(biāo)點(diǎn)符號(hào)(通常為連字符)作為分隔符將結(jié)果劃分為單詞羡疗。
- 推薦:如果有任何詞在常用的情況下已經(jīng)具有常規(guī)的CamelCase外觀,將其拆分為其組成部分(例如别洪,“AdWords”成為“ad words”)叨恨。注意,諸如“iOS”這樣的詞本身不是真正的駱駝情況蕉拢;它違反任何慣例特碳,因此本建議不適用诚亚。
- 將所有字符都轉(zhuǎn)為小寫,僅僅將第一個(gè)字符轉(zhuǎn)為大寫:
- ...將所有字符全大寫
- ...除第一個(gè)字符外午乓,將所有字符全小寫
- 最后站宗,將所有單詞連接成一個(gè)詞。
注意益愈,原始單詞樣式幾乎完全被忽略梢灭。示例:
| 文本形式 | 正確 | 錯(cuò)誤 |
| ------ | ------ | ------ |
|"XML HTTP request" | XmlHttpRequest | XMLHTTPRequest|
|"new customer ID" | newCustomerId | newCustomerID|
|"inner stopwatch" | innerStopwatch | innerStopWatch|
|"supports IPv6 on iOS?" | supportsIpv6OnIos | supportsIPv6OnIOS|
|"YouTube importer" | YouTubeImporter
YoutubeImporter *| |
其中*表示可接受,但不推薦蒸其。
提示:一些單詞在英語(yǔ)中有模糊的連字符:例如“nonempty”和“non-empty”都是正確的敏释,所以方法名稱checkNonempty和checkNonEmpty也都是正確的。
6 編程實(shí)踐
6.1 @Override:能用則用
只要是合法的摸袁,就把@Override注解給用上钥顽。這包括重寫超類方法的類方法、實(shí)現(xiàn)接口方法的類方法靠汁、以及重定義超接口方法的接口方法蜂大。
例外:當(dāng)父方法為@Deprecated時(shí),可以省略@Override蝶怔。
6.2 捕獲的異常:不能忽視
除下面的例子奶浦,對(duì)捕獲的異常不做響應(yīng)極少是正確的。(典型的響應(yīng)方式是打印日志踢星,如果不行澳叉,則把它當(dāng)作一個(gè)AssertionError重新拋出。)
如果它確實(shí)是不需要在catch塊中做任何響應(yīng)沐悦,需要做注釋加以說(shuō)明(如下面的例子)成洗。
try {
int i = Integer.parseInt(response);
return handleNumericResponse(i);
} catch (NumberFormatException ok) {
// it's not numeric; that's fine, just continue
}
return handleTextResponse(response);
例外:在測(cè)試中,如果一個(gè)捕獲的異常被命名為expected所踊,則它可以被不加注釋地忽略泌枪。下面是一種非常常見(jiàn)的情形概荷,用以確保所測(cè)試的方法會(huì)拋出一個(gè)期望中的異常秕岛,因此在這里就沒(méi)有必要加注釋。
try {
emptyStack.pop();
fail();
} catch (NoSuchElementException expected) {
}
6.3 靜態(tài)成員:使用類進(jìn)行調(diào)用
使用類名調(diào)用靜態(tài)的類成員误证,而不是具體某個(gè)對(duì)象或表達(dá)式继薛。
Foo aFoo = ...;
Foo.aStaticMethod(); // good
aFoo.aStaticMethod(); // bad
somethingThatYieldsAFoo().aStaticMethod(); // very bad
6.4 Finalizers: 禁用
極少會(huì)去重載Object.finalize。
提示:不要這么做愈捅,不得已非要這么做的話遏考,請(qǐng)先仔細(xì)閱讀并理解Effective Java Item 7: "Avoid Finalizers",非常小心蓝谨,最后還是不要這么做灌具。
7 Javadoc
7.1 格式
7.1.1 一般形式
Javadoc塊的基本格式如下所示:
/**
* Multiple lines of Javadoc text are written here,
* wrapped normally...
*/
public int method(String p1) { ... }
或者是以下單行形式:
/** An especially short bit of Javadoc. */
基本形式總是可以接受的青团。若整個(gè)Javadoc塊(包括注釋標(biāo)記)可以放在單個(gè)行上,則可以將其替換為單行形式咖楣。請(qǐng)注意督笆,這僅適用于沒(méi)有諸如@return之類的塊標(biāo)簽的情況。
7.1.2 段落
空行(即诱贿,只包含最左側(cè)星號(hào)的行)會(huì)出現(xiàn)在段落之間和Javadoc標(biāo)記(@XXX)之前(如果有的話)娃肿。除了第一個(gè)段落,每個(gè)段落第一個(gè)單詞前都有標(biāo)簽<p>珠十,并且它和第一個(gè)單詞間沒(méi)有空格料扰。
7.1.3 塊標(biāo)記
標(biāo)準(zhǔn)的塊標(biāo)記標(biāo)記按以下順序出現(xiàn):@param、@return焙蹭、 @throws晒杈、@deprecated,且這四種類型不能出項(xiàng)空描述孔厉。當(dāng)描述無(wú)法在一行中容納時(shí)桐智,連續(xù)行需要至少在@縮進(jìn)的基礎(chǔ)上再縮進(jìn)至少4個(gè)空格。
7.2 摘要片段
每個(gè)類或成員的Javadoc以一個(gè)簡(jiǎn)短的摘要片段開(kāi)始烟馅。這個(gè)片段是非常重要的说庭,在某些情況下,它是唯一出現(xiàn)的文本郑趁,比如在類和方法索引中刊驴。
這只是一個(gè)小片段,可以是一個(gè)名詞短語(yǔ)或動(dòng)詞短語(yǔ)寡润,但不是一個(gè)完整的句子捆憎。它不會(huì)以A {@code Foo} is a...
或This method returns...
開(kāi)頭,它也不會(huì)是一個(gè)命令式語(yǔ)句梭纹,如Save the record.
躲惰。然而,由于開(kāi)頭大寫及被加了標(biāo)點(diǎn)变抽,它看起來(lái)就像是個(gè)完整的句子础拨。
提示:一個(gè)常見(jiàn)的錯(cuò)誤是把簡(jiǎn)單的Javadoc寫成 /** @return the customer ID /,這是不正確的绍载。它應(yīng)該寫成/* Returns the customer ID. */诡宗。
7.3 何處需要使用Javadoc
至少在每個(gè)public類及它的每個(gè)public和protected成員處使用Javadoc,以下是一些例外击儡。
如第7.3.3節(jié)“非必須的Javadoc”中所述塔沃,還可能存在其他Javadoc內(nèi)容。
7.3.1 例外:不言自明的方法
對(duì)于簡(jiǎn)單明顯的方法如getFoo阳谍,Javadoc是可選的蛀柴。這種情況下除了寫"Returns the foo"螃概,確實(shí)也沒(méi)有什么值得寫了。
提示:如果有一些相關(guān)信息是需要讀者了解的鸽疾,那么以上的示例不應(yīng)作為忽視這些信息的理由谅年。例如,對(duì)于名為getCanonicalName的方法肮韧,不要省略其文檔(文檔可以僅僅是/** Returns the canonical name. */)融蹂,可能讀者并不明白“canonical name”具體指什么。
7.3.2 例外:重載
如果一個(gè)方法重載了超類中的方法弄企,那么Javadoc并非必需的超燃。
7.3.3 非必需Javadoc
其他類和成員可以根據(jù)需要使用Javadoc。
無(wú)論何時(shí)使用實(shí)現(xiàn)注釋來(lái)定義類或成員的總體用途或行為拘领,該注釋都將改為Javadoc(使用/**)意乓。
雖然不強(qiáng)制要求遵循章節(jié)7.1.2、章節(jié)7.1.3和章節(jié)7.2的Javadoc格式化規(guī)則约素,但還是建議遵循届良。