Google Java 風格指南(Google Java Style Guide)

官方地址 google.github.io

本文檔作為 Google 的 Java™ 程式語言源程式碼編碼標準的完整定義。當且僅當它遵守此處的規則時,Java 源文件才被描述為 Google 風格。

前言

聲明:在原文擋基礎上做了一次翻譯並總結了一下具體內容,換了一下排版樣式等等。

在此也參考了另外一篇已經有很長時間的翻譯版://hawstein.com/2014/01/20/google-java-style/

要提一點的是,中國的話可能更熟悉阿里的開發手冊📎Java開發手冊(嵩山版).pdf或者《Effective Java》(Gitee://gitee.com/lin-mt/effective-java-third-edition 在線網://www.mianshigee.com/tutorial/effective-java-3rd-chinese/docs-readme.md),
所以Google的開發規範可能不怎麼熟悉,甚至和我一樣有點感覺不習慣。畢竟只是一種形式而已,不能說用了Google規範,就可以進Google,甚至程式碼更流暢,只能說,相互參照一些內容,可以讓程式碼更方便閱讀以及維護吧。

(不過,個人可能還是習慣了中國的阿里,Effective java 這本書還沒有看完,唉,還是太懶了)


一、簡介

本文檔作為 Google 的 Java™ 程式語言源程式碼編碼標準的完整定義。當且僅當它遵守此處的規則時,Java 源文件才被描述為 Google 風格。

與其它的編程風格指南一樣,這裡所討論的不僅僅是編碼格式美不美觀的問題, 同時也討論一些約定及編碼標準。然而,這份文檔主要側重於我們所普遍遵循的規則, 對於那些不是明確強制要求的,我們盡量避免提供意見。

1.1 術語說明

在本文件中,除非另有說明:

  1. 術語 *class* 包含地用於表示 「普通」 類、枚舉類、介面或註解類型 ( @interface)。
  2. 術語成員(of a class)包含性地用於表示嵌套的類、欄位、方法或構造函數;也就是說,除了初始化程式和注釋之外的類的所有頂級內容。
  3. 術語comment只用來指代實現的注釋(implementation comments),我們不使用「documentation comments」一詞,而是用Javadoc。

1.2 指導說明

本文檔中的示例程式碼是非規範的。也就是說,雖然這些示例採用 Google 風格,但它們可能無法說明表示程式碼的唯一*****時尚方式。示例中的可選格式選擇不應作為規則強制執行*。(不強制你使用這種規範)


二、源文件基礎

2.1 文件名

源文件以其最頂層的類名來命名,大小寫敏感,文件擴展名為.java。

2.2 文件編碼:UTF-8

源文件以 UTF-8 編碼。

2.3 特殊字元

2.3.1 空白字元

除了行終止符序列之外,ASCII 水平空格字元 ( 0x20 ) 是唯一出現在源文件中任何位置的空白字元。這意味著:

  1. 字元串和字元文字中的所有其他空白字元都被轉義。
  2. 製表符用於縮進。

2.3.2 特殊轉義序列

對於任何具有 特殊轉義序列\b\t\n\f\r、 和 )的字元\", 將使用該序列而不是相應的八進位(例如 )或 Unicode(例如 )轉義。\'``\\``\012``\u000a

2.3.3 非 ASCII 字元

對於剩餘的非 ASCII 字元,使用實際的 Unicode 字元(例如 )或等效的 Unicode 轉義 符(例如 ) \u221。選擇僅取決於使程式碼更易於閱讀和理解的方式,儘管強烈建議不要使用 Unicode 轉義字元串文字和注釋。

提示:在 Unicode 轉義情況下,有時甚至在使用實際的 Unicode 字元時,解釋性注釋也會很有幫助。

例子 討論
String unitAbbrev = "μs"; 最佳:即使沒有注釋也非常清楚。
String unitAbbrev = "\u03bcs"; // "μs" 允許,但沒有理由這樣做。
String unitAbbrev = "\u03bcs"; // Greek letter mu, "s" 允許,但尷尬且容易出錯。
String unitAbbrev = "\u03bcs"; 很差:讀者不知道這是什麼。
return '\ufeff' + content; // byte order mark 好:對不可列印的字元使用轉義符,並在必要時進行注釋。

提示: 永遠不要由於害怕某些程式可能無法正確處理非ASCII字元而讓你的程式碼可讀性變差。當程式無法正確處理非ASCII字元時,它自然無法正確運行, 你就會去fix這些問題的了。(言下之意就是大膽去用非ASCII字元,如果真的有需要的話)


三、源文件結構

源文件按順序包括:

  1. 許可或版權資訊(如果需要)
  2. 包裝聲明(package語句)
  3. 導入語句(import語句)
  4. 一個頂級類(只有一個)

恰好一個空行分隔存在的每個部分(以上每個部分之間用一個空行隔開)。

3.1 許可或版權資訊(如果需要)

如果一個文件包含許可證或版權資訊,那麼它應當被放在文件最前面。

3.2 包裝聲明(package語句)

package語句不換行,列限制(4.4節)並不適用於package語句。(即package語句寫在一行里)

3.3 導入語句(import語句)

3.3.1 import不要使用通配符

即,不要出現類似這樣的import語句:import java.util.*;

3.3.2 無換行

import語句不換行,列限制(4.4節,列限制:100)並不適用於import語句。(每個import語句獨立成行)

3.3.3 排序和間距

import的順序如下。

  1. 所有的靜態導入在一個區塊中。

  2. 所有非靜態進口在一個區塊中。

如果同時有靜態和非靜態的導入,則用一個空行來分隔這兩個塊。在導入語句之間沒有其他空行。

每個區塊中,導入的名字以ASCII排序方式出現。(注意:這與導入語句的ASCII排序不同,因為’.’排序在’;’之前)

3.3.4 沒有靜態導入的類

靜態導入不用於靜態嵌套類。它們是用普通的導入方式導入的。

關於靜態導入可參考這篇文章://www.cnblogs.com/mengdd/archive/2013/01/23/2873312.html

百度知道 解釋:

img

3.4 類聲明

3.4.1 只有一個頂層類的聲明

每個頂層類都駐留在一個自己的源文件中。

3.4.2 類內容的排序

你為你的類的成員和初始化器選擇的順序對可學習性有很大影響。然而,如何做到這一點並沒有一個正確的秘訣;不同的類可能會以不同的方式排列其內容。

重要的是,每個類都使用一些邏輯順序,如果有人問起,其維護者可以解釋。例如,新的方法不會被習慣性地添加到類的末尾,因為這將產生 “按添加日期的時間順序 “排序,而這並不是一個邏輯排序

3.4.2.1 重載:從不拆分

當一個類有多個構造函數或多個同名方法時,這些方法會按順序出現,中間沒有其他程式碼(甚至沒有私有成員)


四、格式化

術語說明:類塊結構是指類、方法或構造函數的主體。請注意,根據第4.8.3.1節關於數組初始化器的規定,任何數組初始化器都可以選擇性地被當作類塊結構來處理

4.1 大括弧

4.1.1 在可選的地方使用大括弧

大括弧用於if、else、for、do和while語句,即使主體為空或只包含一條語句“

4.1.2 非空塊:K & R 風格

大括弧遵循 Kernighan 和 Ritchie 樣式(「 Egyptian 括弧」),用於非空塊和塊狀結構:

  • 左大括弧前不換行

  • 左大括弧後換行

  • 右大括弧前換行

  • 如果右大括弧是一個語句、函數體或類的終止,則右大括弧後換行; 否則不換行。例如,如果右大括弧後面是else或逗號,則不換行。

例子:

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();
    }
  }
};

枚舉類的一些例外情況在第 4.8.1 節, 枚舉類中給出。

4.1.3 空塊:可以是簡潔的

一個空塊或類似塊的結構可以是K&R風格的(如4.1.2節所述)。另外,它可以在打開後立即關閉,中間沒有字元或換行({}),除非它是多塊語句的一部分(直接包含多個塊的語句:if/else或try/catch/finally)。

例子:

//這是可以接受的
void doNothing() {}

// 這也是可以接受的
void doNothingElse() {
}
// 這是不可以的。在一個多塊語句中不能有簡潔的空塊
try {
    doSomething();
  } catch (Exception e) {}

4.2 塊縮進:+2 個空格

每當一個新的區塊或類似區塊的結構被打開時,縮進就會增加兩個空格。當區塊結束時,縮進會恢復到之前的縮進水平。縮進程度適用於整個塊中的程式碼和注釋。(參見第4.1.2節中的例子,非空塊:K & R風格)。

4.3 每行一個語句

每條語句後面都有一個換行符。

4.4 列數限制:100

Java程式碼有一個100個字元的列限制。一個 “字元 “是指任何Unicode程式碼點。除了下面提到的情況,任何超過這個限制的行都必須進行換行,如第4.5節 “換行 “所解釋的。

每個Unicode碼位都算作一個字元,即使它的顯示寬度有大有小。例如,如果使用全寬字元,你可以選擇在本規則嚴格要求的地方提前換行。

例外:

  1. 不可能遵守列限制的行(例如,Javadoc中的長URL,或長的JSNI方法引用)。
  2. package和import語句(見第3.2節package語句和3.3節import語句)。
  3. 注釋中的命令行,可以剪切並粘貼到shell中。

4.5 換行

術語說明:當本來可能合法地佔用一行的程式碼被分成多行時,這種活動被稱為換行。

沒有一個全面的、決定性的公式能準確地顯示在任何情況下如何換行。很多時候,對同一段程式碼有幾種有效的換行方式。

注意:雖然換行的典型原因是為了避免超出列限制,但即使是實際上適合列限制的程式碼 可以由作者自行決定換行。

提示提取方法或局部變數可以在不換行的情況下解決程式碼過長的問題(是合理縮短命名長度吧)

4.5.1 在哪裡斷開

自動換行的基本準則是:更傾向於在更高的語法級別處斷開,此外:

  1. 當在非賦值運算符處斷行時,斷行出現在符號之前。(請注意,這與 Google 風格中用於其他語言(例如 C++ 和 JavaScript)的做法不同。)
  • 這也適用於以下 「類似運算符」 的符號:

    • 點分隔符 ( .)

    • 方法引用的兩個冒號 ( ::)

    • 類型綁定 ( <T extends Foo & Bar>) 中的 & 符號

    • catch 塊 ( catch (FooException | BarException e)) 中的管道。

  1. 當在賦值運算符處斷行時,斷行通常出現在符號之後,但任何一種方式都是可以接受的。
  • 這也適用於增強 for(「foreach」)語句中的 「類似賦值運算符」 的冒號。
  1. 一個方法或構造函數的名稱要與它後面的開放小括弧 ( () 相連。

  2. 逗號 ( ,) 始終與它前面的標記相連。

  3. 在lambda的箭頭附近永遠不會斷行,但如果lambda的主體是由單個非代數表達式組成,,則可以在箭頭之後立即斷行

例子:

MyLambda<String, Long, Object> lambda =
    (String label, Long value, Object obj) -> {
        ...
    };

Predicate<String> predicate = str ->
    longExpressionInvolving(str);

注意:換行的主要目標是擁有清晰的程式碼,而不一定是適合最少行數的程式碼。

4.5.2 自動換行時縮進至少+4個空格

當換行時,第一行之後的每一行(每一個延續行)至少要從原行縮進+4。

當有多個延續行時,縮進可以根據需要超過+4。一般來說,兩個延續行使用相同的縮進水平,當且僅當它們以語法上平行的元素開始時。

第4.6.3節 “水平對齊 “討論了不鼓勵的做法,即使用可變的空格數使某些標記與前幾行對齊

4.6 空白

4.6.1 垂直空白

以下情況需要使用一個空行:

  1. 在一個類的連續成員或初始化器之間:欄位、構造函數、方法、嵌套類、靜態初始化器、以及實例初始化器。
  • 例外:兩個連續的欄位之間的空行(它們之間沒有其他程式碼)是可選的。這樣的空行是用來創建欄位的邏輯分組的。

  • 例外:第 4.8.1 節介紹了枚舉常量之間的空行。

  1. 根據本文檔其他部分的要求(例如第 3 節, 源文件結構和第 3.3 節, 導入語句)。

單獨的空行也可以出現在任何可以提高可讀性的地方,例如,在語句之間,將程式碼組織成合乎邏輯的小節。在類的第一個成員或初始化器之前,或最後一個成員或初始化器之後,既不鼓勵也不反對出現空行。

允許有多個連續的空行,但從不要求(或鼓勵)。

4.6.2 水平空白

除了語言或其他風格規則的要求外,除了字面意義、注釋和Javadoc外,單個ASCII空格也出現在以下地方。

  1. 分隔任何保留字與緊隨其後的左括弧( ( )(如if, for catch等)。
  2. 分隔任何保留字與其前面的右大括弧( } )(如else, catch)
  3. 在任何左大括弧 ( {) 之前,有兩個例外:
  • @SomeAnnotation({a, b}) (不使用空格)

  • String[][] x = {{"foo"}};(大括弧間沒有空格,見下面第八項)

  1. 在任何二元或三元運算符的兩側。這也適用於以下 「類運算符」 的符號:
  • 合取類型界限中的 & 符號: <T extends Foo & Bar>

  • 處理多個異常的 catch 塊的管道: catch (FooException | BarException e)

  • 增強型 for(「foreach」)語句中的冒號 ( : )

  • lambda 表達式中的箭頭: (String str) -> str.length()

但不是

  • 方法引用的兩個冒號 ( ::),寫成Object::toString

  • 點分隔符 ( .),寫成 object.toString()

  1. ,:;或右括弧 ( ))
  2. 在開始行末注釋的雙斜線(//)的兩側。這裡,允許有多個空格,但不是必須的。
  3. 在一個聲明的類型和變數之間: List<String> list
  4. 在數組初始值設定項的兩個大括弧內都是 可選的
  • new int[] {5, 6}並且 new int[] { 5, 6 }都是有效的

9.在類型注釋和[]...之間。

Note:此規則永遠不會被解釋為要求或禁止在行首或行尾添加額外的空格;它只針對內部空間。

4.6.3 水平對齊:不做要求

術語說明:水平對齊是在你的程式碼中增加可變數量的額外空間,目的是使某些標記出現在前幾行的某些其他標記的正下方。(水平對齊指的是通過增加可變數量的空格來使某一行的字元與上一行的相應字元對齊)

這種做法是允許的,但絕不是Google風格所要求的。在已經使用了水平對齊的地方,甚至不需要保持水平對齊。

下面是一個沒有對齊的例子,然後使用對齊

private int x; // 這很好
private Color color; // 這個也可以

private int   x;      // 允許的,但將來會被編輯
private Color color;  // 可以不對齊

考慮一個可能會出現的問題,但現在可能會出現未來的變化。更常見的是它會提示編碼器(可能是現在)也調整這行的空白,可能觸發更改行級聯的重新定義。會導致沒有任何意義的重要工作,但在最好的情況下,它仍然會顯示歷史資訊,減少慢閱者的速度並混合破解。

提示:對齊可以提高可讀性,但會給未來的維護帶來問題。考慮到未來的變化,只需要觸及一行。這種改變可能會使以前令人滿意的格式被弄亂,這是被允許的。但更多的時候,它會促使編碼者(也許是你)對附近幾行的空白進行調整,可能會引發一連串的改寫。這一行的變化現在有一個 “爆炸半徑”。這在最壞的情況下會導致無意義的忙碌,但在最好的情況下,它仍然會破壞版本歷史資訊,拖慢審查人員的速度,加劇合併衝突。

4.7 分組括弧:推薦

只有當作者和審查者一致認為沒有小括弧,程式碼就不會被誤解,也不會使程式碼更容易閱讀時,才會省略可選的分組小括弧。假設每個讀者都記住了整個Java操作符優先順序表是不合理的

4.8 具體結構

4.8.1 枚舉類

在枚舉的後面也允許有引號的空格,換行符是可選的。

private enum Answer {
  YES {
    @Override public String toString() {
      return "yes";
    }
  },

  NO,
  MAYBE
}

一個沒有方法也沒有常量文檔的枚舉類可以選擇性地被格式化為數組初始化器(參見第4.8.3.1節關於數組初始化器),

private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }

因為枚舉類是類,所以所有其他用于格式化類的規則都適用。

4.8.2 變數聲明

4.8.2.1 每個聲明只有一個變數

每個變數聲明(欄位或局部)只聲明一個變數:不使用諸如int a, b;的聲明。

例外:在for循環的頭部可以接受多個變數的聲明。

4.8.2.2 在需要時聲明

局部變數不習慣於在其包含的塊或塊狀結構的開始處聲明。相反,局部變數會在靠近它們第一次使用的地方被聲明(在合理範圍內),以最小化它們的範圍。局部變數的聲明通常有初始化器,或者在聲明後立即被初始化。

4.8.3 數組

4.8.3.1 數組初始化:可寫成塊狀結構

任何數組的初始化器都可以有選擇地被格式化為 “類塊結構”。例如,下面這些都是有效的(不是一個詳盡的列表)。

new int[] {           new int[] {
  0, 1, 2, 3            0,
}                       1,
                        2,
new int[] {             3,
  0, 1,               }
  2, 3
}                     new int[]
                          {0, 1, 2, 3}

4.8.3.2 沒有C語言風格的數組聲明

方括弧構成類型的一部分,而不是變數的一部分。String[] args,而不是String args[]。

4.8.4 switch語句

術語說明:switch語句的大括弧內是一個或多個語句組。每個語句組由一個或多個switch標籤(either case FOO: or default:)組成,後面是一個或多個語句(或者,對於最後一個語句組,是零個或多個語句)

4.8.4.1 縮進

與其他塊一樣,switch塊的任何內容縮進+2。

在切換標籤之後,會有一個換行,並且縮進程度會增加+2,就像一個塊被打開一樣。接下來的切換標籤會回到之前的縮進水平,就像一個區塊被關閉一樣。(每個switch標籤後新起一行,再縮進2個空格,寫下一條或多條語句。)

4.8.4.2 Fall-through:注釋

在switch塊中,每個語句組要麼突然終止(用break、continue、return或拋出的異常),要麼用注釋來表示執行將或可能繼續到下一個語句組。任何能傳達 “穿越 “概念的注釋都是足夠的(通常是//穿越)。這個特殊的注釋在switch塊的最後一個語句組中是不需要的。

例子:

switch (input) {
  case 1:
  case 2:
    prepareOneOrTwo();
    // fall through
  case 3:
    handleOneTwoOrThree();
    break;
  default:
    handleLargeNumber(input);
}

注意,在case 1:之後不需要注釋,只需要在語句組的末章節附註釋。

4.8.4.3default是存在的

每個switch語句都包括一個default語句組,即使它不包含任何程式碼。

例外:枚舉類型的switch語句可以省略默認語句組,如果它包括涵蓋該類型所有可能值的明確案例。這使得IDE或其他靜態分析工具能夠在遺漏任何案例時發出警告

4.8.5 註解(Annotations)

適用於類、方法或構造函數的註解緊接著出現在文檔塊之後,每個註解都被列在自己的一行中(也就是說,每行一個註解)。這些換行並不構成換行(第4.5節,換行),所以縮進程度不會增加。

例子:

@Override
@Nullable
public String getNameIfPresent() { ... }

例外:一個單一的無參數註解反而可以和簽名的第一行一起出現,比如說。

@Override public int hashCode() { ... }

適用於一個欄位的注釋也緊隨在文檔塊之後,但在這種情況下,多個註解(可能是參數化的)可以列在同一行;例如。

@Partial @Mock DataLoader loader;

對於參數、局部變數或類型上的注釋的格式化,沒有特定的規則。

4.8.6 注釋

本節討論實現注釋。 Javadoc 在 Javadoc 第7節中單獨討論。

任何斷行都可以在任意的空白處,然後是一個執行注釋。這樣的注釋使該行成為非空行。

4.8.6.1 區塊注釋風格

區塊注釋的縮進程度與周圍的程式碼相同。它們可以是/* … /風格或//…風格。對於多行的// 注釋,後面的行必須以開頭,與前一行的*對齊。

/*
 * This is          // And so           /* Or you can
 * okay.            // is this.          * even do this. */
 */

注釋不包括在用星號或其他字元繪製的方框內

提示:當寫多行注釋時,如果你想讓自動程式碼格式化器在必要時重新包裝行,請使用/* … */ 樣式,如果你想讓自動程式碼格式化器在必要時重新包裝這些行(段落樣式)。大多數格式化器不會在// … 樣式的注釋塊中重新換行。

4.8.7 修飾語

類和成員的修飾語,如果存在的話,就按照《Java語言規範》推薦的順序出現。

public protected private abstract default static final transient volatile synchronized native strictfp

4.8.8 數字字元

長值整數字使用大寫的L後綴,而不是小寫的(以避免與數字1混淆)。例如,3000000000L而不是3000000000l。


五、命名約定

5.1 所有標識符的共同規則

識別符只使用ASCII字母和數字,在下面提到的少數情況下,還有下劃線。因此,每個有效的標識符名稱都由正則表達式\w+匹配。

在Google風格中,使用特殊的前綴或後綴。例如,這些名稱不是Google Style:name_、mName、s_name和kName。

5.2 按標識符類型劃分的規

5.2.1 包名

包的名稱都是小寫的,連續的單詞簡單的連接在一起(沒有下劃線)。例如,com.example.deepspace,而不是com.example.deepSpace或com.example.deep_space。

5.2.2 類名

類的名稱用UpperCamelCase書寫。

類名通常是名詞或名詞短語。例如,Character或ImmutableList。

介面名稱也可以是名詞或名詞短語(例如,List),但有時可能是形容詞或形容詞短語(例如,可讀)。

對於註解類型的命名,沒有具體的規則,甚至沒有完善的慣例。

測試類的命名以它們所測試的類的名稱開始,並以Test結束。例如,HashTest或HashIntegrationTest。

5.2.3 方法名稱

方法名稱以小寫字母(lowerCamelCase)書寫。

方法名稱通常是動詞或動詞短語。例如,sendMessage或stop。

JUnit測試方法名稱中可以出現下劃線,以分隔名稱中的邏輯組件,每個組件用小寫的CamelCase書寫。一個典型的模式是_,例如 pop_emptyStack。沒有一個正確的方法來命名測試方法。

5.2.4 常量名

常量名稱使用CONSTANT_CASE:全部為大寫字母,每個字之間用一個下劃線分開。但究竟什麼是常量?

常量是靜態的最終欄位,其內容是不可改變的,其方法沒有可檢測的副作用。這包括基元、字元串、不可變類型和不可變類型的不可變集合。如果實例的任何可觀察狀態可以改變,那麼它就不是常量。僅僅打算不改變對象是不夠的。例子:

// 常量
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 }

// 不是常量
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"};

這些名稱通常是名詞或名詞短語。

5.2.5 非常量欄位名

這些名字通常是名詞 非恆定欄位名(靜態或其他)用小寫的CamelCase書寫。

這些名稱通常是名詞或名詞短語。例如,computedValues或index.或名詞短語。

5.2.6 參數名

參數名稱以小寫字母(lowerCamelCase)書寫。

應避免在公共方法中使用一個字元的參數名。

5.2.7 局部變數名

局部變數的名字是用小寫的CamelCase寫的。

即使是最終的和不可改變的,局部變數也不被認為是常量,也不應該被寫成常量。

5.2.8 類型變數名

每個類型變數有兩種命名方式:

  • 一個大寫字母,後面可以選擇一個數字(比如E、T、X、T2)。
  • 用類的形式命名(見第5.2.2節,類名),後面是大寫字母T(例子:RequestT,FooBarT)。

5.3 駝峰式命名法(CamelCase)

有時,將一個英文短語轉換為駝峰大小寫的合理方式不止一種,例如當縮寫或不尋常的結構如 “IPv6 “或 “iOS “出現時。為了提高可預測性,Google Style規定了以下(近乎)確定性的方案。

從名稱的散文形式開始:

  1. 將短語轉換為普通ASCII碼,並去掉任何撇號。例如,”Müller’s algorithm “可能變成 “Muellers algorithm”。
  2. 將這一結果分成幾個詞,在空格和任何剩餘的標點符號(通常是連字元)上進行分割。
    • 建議:如果任何一個詞在常用的情況下已經有了傳統的駱駝大寫的外觀,就把它分成它的組成部分(例如,”AdWords “變成 “ad words”)。請注意,像 “iOS “這樣的詞本身並不是真正的駝峰大寫;它違背了任何慣例,所以這一建議並不適用。
  1. 現在,所有的東西都小寫(包括首字母縮寫),然後只將第一個字元大寫。
    • 每個單詞的第一個字母都大寫,來得到大駝峰式命名。
    • 除了第一個單詞,每個單詞的第一個字母都大寫,來得到小駝峰式命名。
  1. 最後,將所有的詞連接成一個單一的標識符。

請注意,原始單詞的大小寫幾乎被完全忽略了。例子。

形式 正確 不正確
“XML HTTP request” XmlHttpRequest XMLHTTPRequest
“new customer ID” newCustomerId newCustomerID
“inner stopwatch” innerStopwatch innerStopWatch
“supports IPv6 on iOS?” supportsIpv6OnIos supportsIPv6OnIOS
“YouTube importer” YouTubeImporter YoutubeImporter*

*可以接受,但不推薦

注意:有些詞在英語中是模糊的連字元:例如 “nonempty “和 “non-empty “都是正確的,所以方法名稱checkNonempty和checkNonEmpty也同樣都是正確的。


六、編程實踐

6.1 @Override: 始終使用

只要一個方法是合法的,就會用@Override註解來標記。這包括覆蓋超類方法的類方法、實現介面方法的類方法、以及重新指定超介面方法的介面方法。

例外。當父方法是@Deprecated時,@Override可以被省略。

6.2 捕獲的異常:不被忽視

除了下面提到的情況,很少有對捕獲的異常不做任何反應的情況。(典型的反應是記錄它,或者如果它被認為是 “不可能的”,將它作為AssertionError重新拋出)。

當真正適合在捕獲塊中不採取任何行動時,將在注釋中解釋這樣做的理由。

try {
  int i = Integer.parseInt(response);
  return handleNumericResponse(i);
} catch (NumberFormatException ok) {
  // it's not numeric; that's fine, just continue
}
return handleTextResponse(response);

異常:在測試中,如果一個被捕獲的異常的名字是或以預期開頭,可以不加註釋而被忽略。下面是一個非常常見的習慣,用來確保被測試的程式碼確實拋出了一個預期類型的異常,所以這裡不需要注釋。

try {
  emptyStack.pop();
  fail();
} catch (NoSuchElementException expected) {
}

6.3 靜態成員:使用類的限定

當對靜態類成員的引用必須被限定時,它被用該類的名稱來限定,而不是用該類的類型的引用或表達式來限定。

Foo aFoo = ...;
Foo.aStaticMethod(); // good
aFoo.aStaticMethod(); // bad
somethingThatYieldsAFoo().aStaticMethod(); // very bad

6.4 Finalizers: 禁用

覆蓋Object.finalize是極為罕見的。

提示:不要這樣做。如果你一定要這麼做,首先要仔細閱讀並理解Effective Java第7項 “避免使用最終處理器”,然後不要這麼做。


七、Javadoc

7.1格式

7.1.1一般形式

Javadoc塊的基本格式如本例所示

/**
 * 多行Javadoc文本寫在這裡。
 * 正常包裝...
 */
public int method(String p1) { ... }

或者在這個單行的例子里:

/** An especially short bit of Javadoc. */

基本形式總是可以接受的。當Javadoc塊的全部內容(包括注釋標記)可以放在一行中時,可以用單行形式代替。請注意,這隻適用於沒有諸如@return這樣的塊標記的情況。。

7.1.2 段落

段落之間有一個空行–即只包含對齊的前導星號(*)的行,如果有塊狀標籤組,則在塊狀標籤組之前出現。除第一段外,每個段落的第一個詞前都有

,後面沒有空格。

7.1.3 塊標籤

任何使用的標準 “塊標記 “都是按照@param, @return, @throws, @deprecated的順序出現的,這四種類型永遠不會以空的描述出現。當一個塊狀標籤不適合在一行中出現時,延續行會從@的位置縮進四個(或更多)空格。

7.2 摘要片段

每個Javadoc塊都以一個簡短的摘要片段開始。這個片段非常重要:它是文本中唯一出現在某些上下文中的部分,比如類和方法的索引。

這是一個片段–名詞短語或動詞短語,不是一個完整的句子。它不是以A {@code Foo} 是一個……開始,或者這個方法返回……,也不是構成一個完整的命令句,如Save the record……。然而,該片段被大寫,並使用標點符號,就像它是一個完整的句子一樣。

提示:一個常見的錯誤是把簡單的Javadoc寫成/** @return the customer ID /,這是不正確的。它應該寫成/* Returns the customer ID. */。

7.3 使用Javadoc的地方

至少,每個公有類,以及公有類中的每個公有或受保護的成員都要有Javadoc,但下面提到的幾個例外情況。

額外的Javadoc內容也可以出現,如第7.3.4節 “非必需的Javadoc “所解釋。

7.3.1 例外:不言而喻的方法

Javadoc對於像getFoo這樣的 “簡單、明顯 “的方法來說是可選的,在這種情況下,除了 “getFoo”,確實沒有其他值得說的東西。

重要的是:如果有一些相關資訊是需要讀者了解的,那麼以上的例外不應作為忽視這些資訊的理由。例如,對於方法名getCanonicalName, 就不應該忽視文檔說明,因為讀者很可能不知道詞語canonical name指的是什麼。

7.3.2 例外:重寫

Javadoc並不總是出現在重寫超類型方法的方法上。

7.3.3 可選的Javadoc

對於包外不可見的類和方法,如有需要,也是要使用Javadoc的。如果一個注釋是用來定義一個類,方法,欄位的整體目的或行為, 那麼這個注釋應該寫成Javadoc,這樣更統一更友好

其他的類和成員根據需要或需要有Javadoc。

每當一個實現注釋被用來定義一個類或成員的整體目的或行為時,該注釋被寫成Javadoc(使用/**)。

非必要的Javadoc並不嚴格要求遵循第7.1.2節、7.1.3節和7.2節的格式規則,但是當然推薦使用它。

Tags: