Goole Java樣式指南[譯]

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)安吁。如:

  1. 如果在非賦值運(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))。
  2. 如果在賦值運(yùn)算符處斷開(kāi)妇智,通常在該符號(hào)后斷開(kāi)滥玷,但是在符號(hào)之前也是可以接受的。
    • 這條規(guī)則也適用于foreach語(yǔ)句中的冒號(hào)巍棱。
  3. 方法名或構(gòu)造函數(shù)名與左括號(hào)(()留在同一行惑畴。
  4. 逗號(hào)(,)與其前面的內(nèi)容留在同一行。
  5. 在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è)空行:

  1. 類內(nèi)連續(xù)的成員或初始化程序之間:字段,構(gòu)造函數(shù)秉馏,方法耙旦,嵌套類,靜態(tài)初始化塊,實(shí)例初始化塊免都。
    • 例外:兩個(gè)連續(xù)字段之間的空行(在它們之間沒(méi)有其他代碼)是可選的锉罐。這樣的空白行根據(jù)需要用于創(chuàng)建字段的邏輯分組。
    • 例外:枚舉常量之間的空行绕娘,章節(jié)4.8.1將介紹脓规。
  2. 據(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è)地方:

  1. 分隔任何保留字(如:if秤掌、for及catch)與緊隨其后的左括號(hào)(()愁铺。
  2. 分隔任何保留字(如:else或catch)與其前面的右大括號(hào)(})。
  3. 在任何左大括號(hào)前({)闻鉴,兩個(gè)例外:
    • @SomeAnnotation({a, b})(不使用空格)
    • String[][] x = {{"foo"}};(兩個(gè)大括號(hào)之間無(wú)空格)
  4. 在任何二元或三元運(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()
  5. 在, : ;及右括號(hào)())后
  6. 如果在一條語(yǔ)句后做注釋似将,則雙斜杠(//)兩邊都要空格。這里可以允許多個(gè)空格蚀苛,但沒(méi)有必要在验。
  7. 類型和變量之間:List<String> list
  8. 在數(shù)組初始值設(shè)定符的兩個(gè)大括號(hào)內(nèi)可選
    • new int[] {5, 6}與new int[] { 5, 6 }都可行
  9. 在類型注釋和[]或...之間

此規(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_般眉、mNames_namekName潜支。

5.2 標(biāo)識(shí)符類型的規(guī)則

5.2.1 包名

包名稱都是小寫甸赃,連續(xù)的單詞連接在一起(無(wú)下劃線)。如com.example.deepspace而非com.example.deepSpacecom.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)始:

  1. 將短語(yǔ)轉(zhuǎn)換為純ASCII并刪除任何省略號(hào)。例如:“Müller's algorithm”可改為“Muellers algorithm”讯檐。
  2. 根據(jù)空格和任何有的標(biāo)點(diǎn)符號(hào)(通常為連字符)作為分隔符將結(jié)果劃分為單詞羡疗。
    • 推薦:如果有任何詞在常用的情況下已經(jīng)具有常規(guī)的CamelCase外觀,將其拆分為其組成部分(例如别洪,“AdWords”成為“ad words”)叨恨。注意,諸如“iOS”這樣的詞本身不是真正的駱駝情況蕉拢;它違反任何慣例特碳,因此本建議不適用诚亚。
  3. 將所有字符都轉(zhuǎn)為小寫,僅僅將第一個(gè)字符轉(zhuǎn)為大寫:
    • ...將所有字符全大寫
    • ...除第一個(gè)字符外午乓,將所有字符全小寫
  4. 最后站宗,將所有單詞連接成一個(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ī)則约素,但還是建議遵循届良。

翻譯自 Google Java Style Guide

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市圣猎,隨后出現(xiàn)的幾起案子士葫,更是在濱河造成了極大的恐慌,老刑警劉巖送悔,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慢显,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡欠啤,警方通過(guò)查閱死者的電腦和手機(jī)荚藻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)洁段,“玉大人应狱,你說(shuō)我怎么就攤上這事§羲浚” “怎么了疾呻?”我有些...
    開(kāi)封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)纽疟。 經(jīng)常有香客問(wèn)我罐韩,道長(zhǎng),這世上最難降的妖魔是什么污朽? 我笑而不...
    開(kāi)封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮龙考,結(jié)果婚禮上蟆肆,老公的妹妹穿的比我還像新娘矾睦。我一直安慰自己,他們只是感情好炎功,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布枚冗。 她就那樣靜靜地躺著,像睡著了一般蛇损。 火紅的嫁衣襯著肌膚如雪赁温。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天淤齐,我揣著相機(jī)與錄音股囊,去河邊找鬼。 笑死更啄,一個(gè)胖子當(dāng)著我的面吹牛稚疹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播祭务,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼内狗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了义锥?” 一聲冷哼從身側(cè)響起柳沙,我...
    開(kāi)封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拌倍,沒(méi)想到半個(gè)月后偎行,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贰拿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年蛤袒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膨更。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡妙真,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出荚守,到底是詐尸還是另有隱情珍德,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布矗漾,位于F島的核電站锈候,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏敞贡。R本人自食惡果不足惜泵琳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧获列,春花似錦谷市、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至巩梢,卻和暖如春创泄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背括蝠。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工鞠抑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人又跛。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓碍拆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親慨蓝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子感混,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355