[翻譯] Google Java 程式風格指南
原文網址:http://blog.mosil.biz/2014/05/java-style-guide/
原文授權聲明(文末也有,只是拿到前面強調一次):
本篇採用創用 CC 姓名標示-非商業性-禁止改作 3.0 台灣 授權條款授權,
如欲轉載請記得註明轉自「[莫希爾(Mosil) 手札][1]」
轉貼行為、轉換成 BBS 版所需之改作(排版)行為
已徵得原作者同意
某些標題長度超過 80 字,為維持 markdown 語法,因此並沒有刻意斷行。
______________________________________________________________________
本篇譯自 [Google Java Style],該文件共分七大部份
1. Introduction
2. Source file basics
3. Source file structure
4. Formatting
5. Naming
6. Programming Practices
7. Javadoc
> **譯注:**
> 本篇譯文會視內容的通順而做一些調整,並不全然照原文的字序來逐文逐句翻譯。若有翻譯錯誤或造成誤會處,也麻煩請各位提出指正,感謝!
>
> **翻譯版本**
> March 21, 2014
>
> **特別感謝**
> - LittleQ 以及 PsMonkey 協助校正。
> - PsMonkey 協助轉成 Markdown 語法。
[Google Java Style]: http://google-styleguide.googlecode.com/
svn/trunk/javaguide.html
1. 引言 (Introduction)
=======================
本文件提供 Google 在使用 Java^(TM) 程式語言撰寫原始碼時,
對程式碼標準的完整定義。
若且唯若 (if and only if),當一份 Java 原始檔符合這份規則
才能被視為 Google 風格。
也如同其他程式風格指南一樣,
這份文件所探討的範圍不僅只有格式美觀的問題,
還包含了其他類型的公約以及程式碼風格。
然而,本文件將著重於通常我們都會依循的必要規則 (hard-and-fast rules),
像那些不那麼明確地需要被執行的部份 (不論是人或工具),
這邊也會避免提供建議。
1.1 術語說明 (Terminology notes)
---------------------------------
在文件中,除非有特別說明,否則
1. Class 一詞泛指 “一般(ordinary)” 的類別(class)、
列舉類別 (enum class) 、介面 (interface)
或是註釋型別(annotation type)(@interface)。
2. Comment 一詞係指實作的註解。
我們不是用 “註解文件(documentation coments)” 這個慣用詞,
而是使用 “Javadoc” 來表達。
其他當遇到時,會以 “術語說明” 為開頭偶爾穿插在文件中。
> **譯注:**
> 為了不要產生用詞的混亂,所以本篇的翻譯會將 Comment 翻譯成「註解」,
> Annotation 翻譯成「註釋」,Javadoc 維持原文就不翻譯成「Java 文件」了。
1.2 指南說明 (Guide notes)
---------------------------
在文件中的範例程式為非規範性的(non-normative)。
這意思是說,程式碼格式應該是要有選擇性的,
而不該把範例視為唯一的風格而將之當作規則強制執行,
那只是要呈現出 Google 設計的程式碼風格。
2. 源碼檔案基礎(Source file basics)
====================================
2.1 檔案名稱 (File name)
-------------------------
源碼檔名包含其最高層級類別 (top-level class) 並區分大小寫,
再加上副檔名 .java 。
2.2 檔案編碼格式 (File encoding):UTF-8
---------------------------------------
源碼檔的編碼格式使用 UTF-8。
2.3 特殊符號 (Special characters)
----------------------------------
### 2.3.1 空白符號 (Whitespace characters) ###
除了每行的結束符號,水平的 ASCII 空格符號 (0×20)
是唯一存在於源碼檔案中的空白符號。這意味著:
1. 除了具有跳脫序列的字符外,所有的字串以及符號間皆要使用空白。
2. 縮排不得使用 Tab 符號。
### 2.3.2 特殊跳脫序列 (Special escape sequences) ###
所有可搭配跳脫符號的字符 (\b、\t、\n、\f、\r、\”、\’以及 \\)
都直接使用,而不必要轉換成相應的八進位 (如:`12`)
或是 Unicode (如:`u000a`) 使用之。
> **譯注:**
> 八進位的 12 以及 Unicode 的 \u000a 皆是指換號符號 \n。
### 2.3.3 Non-ASCII 符號 (Non-ASCII characters) ###
對其他 Non-ASCII 的符號,不論是 actual Unicode 符號 (如:∞)
或是要採用同樣意思的 Unicode escape (如:u221e),
取決於哪個程式碼會更**易於被閱讀以及了解**。
> **Tip:**
> 在使用 Unicode escape 的狀況,或是偶爾使用了 actual Unicode,
> 一個對之的說明注解會對閱讀程式碼者有所幫助
範例:
* `String unitAbbrev = "μs";`
最佳,就算沒有注解也很清楚。
* `String unitAbbrev = "\u03bcs"; // "μs"`
容許, 但沒有理由這麼做。
* `String unitAbbrev = "\u03bcs"; // Greek letter mu, "s"`
容許,但感覺彆扭且容易出錯。
* `String unitAbbrev = "\u03bcs";`
差,完全看不懂在做什麼。
* `return '\ufeff' + content; // byte order mark`
好,當需要使用不可見字符時,使用跳脫符號,並注解之。
> **Tip:**
> 千萬別因為害怕某些程式可能無法處理的 non-ASCII 符號,不敢去使用,
> 進而導致程式碼的可讀性降低。
> 假如真的發生了這種狀況,代表該程式是有問題的,就必需要請他們修正。
3. 源碼檔案架構(Source file structure)
======================================
一個源碼檔案裡需要包括(有順序性):
1. 授權或版權資訊(如果有的話)
2. Package 敘述
3. Import 敘述區
4. 獨立的最高層級類別 (top-level class)
以上各個區段之間要使用一空行 (exactly one blank line) 隔開。
3.1 授權或版權資訊(如果有的話) (License or copyright information, if present)
------------------------------------------------------
如果一個檔案中要呈列授權或版權資訊的話,那他就需要放在這個區段裡。
3.2 Package 敘述 (Package statement)
-------------------------------------
Package 敘述不換行 (not line-wrapped)。
意即每一行的最大字數限制 (請見 4.4 每行字數上限) 不適用於此。
3.3 Import 敘述區 (Import statements)
--------------------------------------
### 3.3.1 Import 不用使用萬用符號 (No wildcard imports) ###
Import 敘述區裡的每一個 import,**皆不要**使用萬用符號 (*)
或是 static 這類的修飾子。
> **譯注:**
> 像是下方這樣的 import 語句都不要使用
> 萬用符號:import java.util.*
> 靜能修飾子:import static java.util.Arrays.sort;
### 3.3.2 不換行 (No line-wrapping) ###
Import 敘述區裡的每一個 import 不換行 (not line-wrapped)。
意即每一行的最大字數限制 (請見 4.4 每行字數上限) 不適用於此。
### 3.3.3 次序與區間 (Ordering and spacing) ###
Import 敘述區中可以按下方幾類,再依次序用一空行做為分群呈現:
* 所有的 static import 一區。
> **譯注:**
> 這點其實跟 3.3.1 衝突了 @@
* `com.google` 的 import 一區。
(這個分群僅用於源碼在 `com.google` 的 package 區間裡)
> **譯注:**
> 必竟這是 google 釋出的文件嘛 XD
* 第三方套件的 import 一區,按 ASCII 編碼次第排序。
* `java import` 一區。
* `javax import` 一區。
分群裡每行 import 敘述皆不要再空行隔開,並依其檔名按 ASCII 編碼次第排序。
3.4 類別宣告 (Class declaration)
---------------------------------
### 3.4.1 獨立的最高類別等級 (Exactly one top-level class declaration) ###
每個最高層級類別都應該存在於自己的源碼檔案中。
### 3.4.2 類別成員的排序 (Class member ordering) ###
類別成員的排序對於能否很好的識別有極大的影響 ,
但實作上並不存在唯一合適的通則。
甚至是在不同的類別裡,其中的成員排序就都不同。
重點在於每個類別的維護者都要能夠按**某個邏輯去排序**其中的成員,
並在被詢問時有辦法解釋之。
舉例來說,在新增一個新的函式,
我們就習慣的將之加在該類別的最末處,
而這樣是不是就造就了一個「按照時間新增」的排序邏輯了呢。
#### 3.4.2.1 多載:永遠不要拆開 (Overloads: never split) ####
當類別中有多個建構式 (constructors) 或是多個同名的函式,
就讓他們依序的放在一起,中間就不要再穿插進不同成員來造成干擾。
4. 格式(Formatting)
===================
**術語說明:**類別中的建構函式 (constructor) 或是函式 (method)
該以區塊結構(block-like construct) 呈現。
特別是像 4.8.3.1 裡陣例的初始值,
所有陣列的初始值只要是以區塊結構呈現,並不限制其格式都要一樣。
4.1 大括號 (Braces)
--------------------
### 4.1.1 即便是有選擇性的狀況,都要使用大括號 (Braces are used where optional) ###
在 if、 else、 for、 do 以及 while 這些敘述裡的程式碼,
就算是空的,或是僅有一行,也都要使用大括號。
### 4.1.2 非空區塊 (Nonempty blocks: K & R style) ###
在內容為非空的區塊結構中,大括號需依序著 Kernighan and Ritchie 風格
(Egyptian Brackets),如下
* 左括號前不要換行
* 在左括號後換行
* 在右括號後換行
* 當右括號是用在一個敘述語法、函式、建構函式或是類別之後,就要換行。
若是像其後接續的是 else 或是逗號就不用。
範例:
return new MyClass() {
@Override public void method() {
if (condition()) {
try {
something();
} catch (ProblemException e) {
recover();
}
}
}
};
但仍是有例外,像是列舉類別,請見 4.8.1。
### 4.1.3 為空的區塊:使其簡潔 (Empty blocks: may be concise) ###
當一個區塊結構為空時,可以將左右括號寫在一起,
不需要在其中加入空白或是換行 ( `{}` )
除非他是多區塊敘述語法的其中一部份
(如 `if/else-if/else` 或是 `try/catch/finally` )。
範例:
void doNothing() {}
4.2 縮排:+2 個空白 (Block indentation: +2 spaces)
---------------------------------------------------
每新增一個區塊結構時,便要在其開始就增加兩個空白。
當區塊結束時,其縮排則返回到和前一層的縮排一致。
而縮排的層級適用於其間的程式碼與註解。(範例請見 4.1.2)
4.3 每行一敘述 (One statement per line)
----------------------------------------
每行的敘述都要換行。
4.4 每列字數限制:80 或 100 (Column limit: 80 or 100)
-----------------------------------------------------
每個專案皆可選擇自己要以每列 80 或是 100 個字元為限制 。
除非是遇到下述例外,否則每行的字數當達到限制時就需要換行,
換行的說明請見 4.5 Line-wrapping。
例外:
1. 不可能滿足在一列的字數限制的條件
(比方說,在 Javadoc 裡很長 URL,或是參考了一個有很長名稱的 JSNI 函式)。
2. `package`以及 `import`敘述
(請見 3.2 Package 敘述 以及 3.3 Import 敘述區)。
3. 註解中,可能會被複製、貼上到 shell 的指令
4.5 換行 (Line-wrapping)
-------------------------
**術語說明**:當程式碼可能在單行裡超過每列限制,而將之拆開到多行中,
這個動作稱之為換行 (Line-wrapping)。
並沒有一種方程式可以完整、明確的告訴我們在所有情況中該如何換行。
而有常有多種合理的方式去對同一段程式碼換行。
> **Tip:**
> 濃縮函式或是區域變數,也許可以解決這種需要被換行的情形。
### 4.5.1 哪裡該斷開 (Where to break) ###
換行的主要原則:傾向在進級的語法 (higher syntactic level) 斷開。還有,
1. 當該行最末的符號若非賦值的等號,則在該符號前換行。
(請注意,這裡和其他實作成 Google 風格的程式語言,
如 C++ 以及 JavaScript 不同。)
* 這也適用於「類運算 (operator-like)」符號:
如點分格符號 ( `.` ),或是像類別限制中的 & 符號
( `<T extends Foo & Bar>` ),以及 catch 區塊
( `catch (FooException | BarException e)` )。
2. 當一行是要斷在賦值的等號時,平常的狀況就是將其斷在該等號之後,
但反之也是可以接受的。
* 這也適用在 `for` 的擴充型 「foreach」所用的冒號,
這種「類等號」(assignment-operator-like) 符號。
3. 左括號 ( `(`) 與函式或是建構函式名留在同一行。
4. 逗號 ( `,`) 與其前方的部份留在同行。
### 4.5.2 每行縮排至少要有一組( 4 個)空白 (Indent continuation lines at least +4 spaces) ###
每個接續在斷行後的第一行開始,
都要比原行加上一組( 4 個)以上的空白來縮排。
當有連續多行時,其縮排可能會超過一組( 4 個)空白。
一般來說,若是連續的兩行都是斷於同級別語法元素時,其縮排階層會是相同的。
4.6 Whitespace
--------------
### 4.6.1 垂直空白 (Vertical whitespace) ###
使用一空行的情形:
1. 在類別中接連在一起的成員(或是初始值)間:
屬性、建構函式、函式、巢狀類別、靜能初始區塊以及實作初始區塊。
* **例外**:兩個接連在一起的屬性間可以考慮使用空行
(沒有其他程式碼在其之間)。這是為了對屬性進行邏輯分組。
2. 在函式區塊裡,需要對程式敘述進行邏輯分組。
3. 在類別中第一個成員前或是最後一個成員後(既不鼓勵也不反動)。
4. 在文字描述間有分章節的需求 (如 3.3 Import statements)。
一行中出現連續多個空白是被允許的,但從沒有這種需求 (或是鼓勵)。
### 4.6.2 水平空白 (Horizontal whitespace) ###
除了語言需求或是風格規則,還有文字、註解、
Javadoc 與單一 ASCII 空白,也僅出現在下列狀況:
1. 隔開所有保留字隨後的左括號( `(`),如 `if` 、 `for` 或 `catch` 。
2. 隔開所有保留字隨後的右大括號( `}` ),如 `else` 或 `catch` 。
3. 所有左大括號( `{` )之前,有兩個例外:
* `@SomeAnnotation({a, b})` (不用空白)
* `String[][] x = {{"foo"}};`
( {{之間不用空白,請見第 8 點下的 Note)
4. 在二或三元運算子的兩側。
也適用於下方提到的「類運算子 (operator-like)」符號:
* 類別限制中的 & 符號 `<T extends Foo & Bar>`
* catch 區塊 `catch (FooException | BarException e)`
* for的擴充型敘述「foreach」中的冒號 ( `:` )
5. 在 `,:;` 之後的右括號( `)` )。
6. 註解用在某行的最後,其開始的雙斜線兩側。在這裡允許多個空白,但沒有要求。
7. 宣告的類別與變數之間: `List<String> list` 。
8. 陣列初始值用的大括號中可使用
* `new int[] {5, 6}` 以及 `new int[] { 5, 6 }` 兩種皆可。
> Important:
> 這個規則從未要求或是禁止增加的空白在一行的開始或是結束,只對在裡面的空白。
### 4.6.3 水平對齊:絕不會特別要求 (Horizontal alignment: never required) ###
**術語說明**:水平對齊主要的目的,
是增加空白來讓程式碼在某一行裡的內容跟上一行相對應的內容對齊。
這做法是被允許的,但他不屬於 Google 風格。
這甚至在已經使用的地方,也沒有被要求修改掉。
這邊舉個例子分別呈現沒有對齊,以及用此方法對齊:
private int x; // 這個沒問題
private Color color; // 這也是
private int x; // 允計,但未來
private Color color; // 可以將他改為不對齊
> **Tip:**
> 對齊是可以增加其可讀性,但他會為日後的維護帶來麻煩。
> 若是在未來要更動其中的一行,就會弄亂原本的格式,而且這也是被允許的。
> 更多時候他會提醒程式人員(也許就是你)去將該行附近的空白調整好,
> 而引發一連串的重構。就因改了那一行而產生的「連鎖反應」。
> 這樣的最糟狀況就是瞎忙,不但影響了歷史資訊,
> 還減慢了程式碼審查者的效率並造成更多合併時的衝突。
4.7 用小括號來分組:推薦 (Grouping parentheses: recommended)
-------------------------------------------------------------
小括號是開發者及程式碼審查者有以下的認定才可省略,
拿掉後不會有機會造成對程式碼的誤解,以及會讓程式碼變得易於閱讀。
我們沒有理由去假設所有人都將 JAVA 運算子的優先表都記下來。
4.8 特定結構 (Specific constructs)
----------------------------------
### 4.8.1 列舉類別 (Enum classes) ###
每個逗號皆要跟著列舉的項目,也可斷行。
一個沒有函式以及說明文字在其中的列舉,可以將其格式寫成像陣列的初始化:
private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }
既然列舉類別是為類別,則其他格式的規則皆視同於類別。
### 4.8.2 變數宣告 (Variable declarations) ###
#### 4.8.2.1 每個變數獨立宣告 (One variable per declaration) ####
每個變數在宣告 (屬性 (field) 或是區域變數 (local)) 時,
僅宣告一個變數,也就是說不要寫成 `int a, b;` 。
#### 4.8.2.2 需要時才宣告,並盡可能給予初始化 (Declared when needed, initialized as soon as possible) ####
區域變數不要習慣在其區塊或是類區塊結構的一開始就全部宣告了。
而是要在該區域變數第一次被使用時才宣告,盡量將他的範圍最小化。
宣告區域變數時通常就會有初始值,或是在其宣告後立刻被初始化。
### 4.8.3 陣列 (Arrays) ###
#### 4.8.3.1 陣列初始化:可為「類區塊結構」 (Array initializers: can be “block-like”) ####
所有陣列在初始化時,只要格式為
「類區塊結構 (block-like construct)」皆可。
如下範例都可以 (並未全部列出):
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 語言風格 (No C-style array declarations) ####
中括號是型別的一部份,而非變數的一部份:
`Srting[] args` 而不是 `String args[]` 。
### 4.8.4 Switch 敘述區塊 (Switch statements) ###
**術語說明**:在 switch 敘述區塊的括號中,有一或多個敘述群組。
每個敘述群組包含一個或多個 switch 標籤
(像是 case FOO: 或是 default: ),其後接續著一或多個程式敘述。
#### 4.8.4.1 縮排 (Indentation) ####
和其他區塊一樣, switch 區塊的內容縮排都是 +2 個空白。
在 switch 標籤後,每新的一行,若是該區塊的開始,
就 +2 個空白做為縮排層級的增加。
並在下一個標籤退回到上一個縮排層級,以表示上一個區塊已經結束。
#### 4.8.4.2 Fall-through:註解 (Fall-through: commented) ####
在 switch 區塊中,每個敘述群組都會有個終止點
(像是 break 、 continue 、 return 或是拋出異常),
或是標上註釋以表將會或是可能繼續往下一個敘述群組執行。
該註解只要足以表達出 fall-through 即可 (通常都是用 // fall through )。
這特殊的註解不需要出現在 switch 區塊中的最後一個敘述。例如:
switch (input) {
case 1:
case 2:
prepareOneOrTwo();
// fall through
case 3:
handleOneTwoOrThree();
break;
default:
handleLargeNumber(input);
}
#### 4.8.4.3 default 一定要有 (The default case is present) ####
每個 switch 敘述的群組中都一定包含 default ,就算裡面沒有程式碼。
### 4.8.5 標注 (Annotations) ###
應用標注 (annotation) 的類別、函式與建構函式緊接於其文件區塊之後,
每個標注皆自己獨立於一行(意即一行一個標注) 。
而這幾行的斷行並不屬於換行 (4.5 Line-wrapping),
所以,縮排層級並不會增加。例如:
@Override
@Nullable
public String getNameIfPresent() { ... }
**例外**: 單個無參數的注解可以和其屬名的第一行放在一起。例如:
@Override public int hashCode() { ... }
應用標注 (annotation) 的屬性 (filed) 緊接於其文件區塊之後,
但在這個狀況下,若是有多個標注可以將其呈列於同一行。例如:
@Partial @Mock DataLoader loader;
參數與區域變數的標注沒有特殊的規則與格式。
### 4.8.6 註解 (Comments) ###
#### 4.8.6.1 註解區塊的風格 (Block comment style) ####
註解區塊的縮排,和其接連的程式碼同一層級。
可用 `/* ... */` 或 `// ...` 。
若是這種註解風格 `/* ... */` 有多行時,
其子行的起始必需有 `*`,而該星號需對齊上一行的 `*` 。
/*
* This is // And so /* Or you can
* okay. // is this. * even do this. */
*/
註解不要將之放在由星號或是其他符號繪製的方框中。
> **Tip:**
> 當在撰寫多行的程式碼時,想要在換行時用程式碼自動格式化的話,
> 就採用 `/* ... */` 風格,因為大部份格式化換行的自動格式化,
> 並沒有支援 `// ...` 這種風格。
### 4.8.7 修飾詞 (Modifiers) ###
類別與成員的修飾詞,其呈現順序就依 Java 語言的規範:
public protected private abstract static final
transient volatile synchronized native strictfp
### 4.8.8 數值行型 (Numeric Literals) ###
`long` 於整數型別後加上後綴大寫字母 `L`,
千萬別用小寫字母 (避免和數字 `1` )。例如,
`3000000000L` 而不要寫成 `30000000000l`。
5. 命名(Naming)
===============
5.1 識別字通則 (Rules common to all identifiers)
-------------------------------------------------
識別字僅能使用英文字母與數字,
若是需要分成兩個部份以上,請使用下底線(_)。
因此,每個符號皆需符合正規表示式 `w+` 。
在 Google style 中會有一些特別的前綴或後綴用法,
舉例像是 `name_`、 `mName`、 `s_name` 以及 `kName`,在這邊都不使用。
5.2 各識別類型的規則 (Rules by identifier type)
------------------------------------------------
### 5.2.1 Package 名命 (Package names) ###
Package 名稱全部小寫,連續單字直接寫在一起(不用下底線(_))。
例如, `com.example.deepspace` ,
不要這樣 `com.example.deepSpace` 或 `com.example.deep_space` 。
### 5.2.2 類別命名 (Class names) ###
類別名稱採用大寫開始的駝峰命名法(UpperCamelCase)。
類別名稱為名詞或是名詞片語。例如, `Character` 或 `ImmutableList`,
介面(interface)也使用名詞或是名詞片語(如: `List`),
但有時候會用形容詞或是形容詞片語取而代之(如: `Readable`)。
### 5.2.3 函式命名 (Method names) ###
函式名稱採用小寫開始的駝峰命名法(lowerCamelCase)。
函式名稱通常都是動詞或是動詞片語。例如, `sendMessage` 或是 `stop` 。
下底線可以做為 JUnit 的測試函式名稱與邏輯元件的分隔。
一個典型的模式 `test<MethodUnderTest>_<state>` ,
範例: `testPop_emptyStack` 。這邊並沒有唯一的正確方式去命名測試函式。
### 5.2.4 常數命名 (Constant names) ###
常數名稱採用 `CONSTANT_CASE` ,全部採用大寫字母,
使用下底線分隔。但究竟什麼是常數呢?
所以有常數的屬性 (Field) 皆是 static final,
但並非所有 static final 屬性的變數皆為常數。
在確定變數是為常數前,需要先考慮他是否真的像一個常數。
舉例來說,當所有在實作的觀察階段會改變時,
那這個變數幾乎就可以肯定不是一個常數。
而通常只是打算永不改變狀態是不夠的。
範例
// 常數
static final int NUMBER = 5;
static final ImmutableList<String> NAMES =
ImmutableList.of("Ed", "Ann");
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 Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};
名稱通常為名詞或是名詞片語。
### 5.2.5 非常數屬性命名 (Non-constant field names) ###
非常數屬性的名稱 (static 或是 其他)
採用小寫開頭的駝峰命名法 (lowerCamelCase) 。
名稱通常為名詞或是名詞片語。
### 5.2.6 參數命名 (Parameter names) ###
參數名稱使用採用小寫開頭的駝峰命名法 (lowerCamelCase) 。
要避免只有一個字符的名稱。
### 5.2.7 區域變數命名 (Local variable names) ###
區域變數名稱採用採用小寫開頭的駝峰命名法 (lowerCamelCase) 。
可以使用縮寫這種較為其他名稱寬鬆的命名方式。
但仍要避免單字符的名稱,除了泛型與迴圈變數。
即便是 final 或是不可變的,區域變數是不可為常數的,
當然,也不該使用常數變數的風格。
### 5.2.8 型別變數命名 (Type variable names) ###
每個型別的命名方式可在下面二法中擇一:
* 一個大寫單字,其後用數字可接續(諸如: `E` 、 `T` 、 `X` 、 `T2` )。
* 可採用類別命名的方式(請見 5.2.2),其後再接一個大寫字母 `T` 。
例如: `RequestT` 、 `FooBarT` 。
5.3 駝峰命名定義 (Camel case: defined)
----------------------------------------
英文詞彙有時並非只有一種合理的駝峰命名表示方式,
也有像「IPv6」或是「iOS」這樣的縮寫或是不尋常的表示法。
為了改善使其規律,Google Style 將使用下方(幾乎)確定的方法。
以散文格式 (prose form) 為名稱的開頭:
1. 字詞皆改為 ASCII 碼並移除所有單引號,
例如,「Mu"ller’s algorithm」可以改變為「Muellers algorithm」。
2. 上述步驟的結果,再依其中的空白以及其餘的符號(通為會連字符號)
做為拆分點,拆成逐一的單字。
* 建議:若所有字都已經有其慣用的駝峰命名用法,
仍是將其拆開(例:「AdWords」變成「ad words」。
注意,像「iOS」這個並不是一個駝峰命名的形式,
這個建議就不適用於這樣的例子。
3. 現在,將每個字母全部變成小寫(包含縮寫),接著,
只要將第一個字母改為大寫:
* … 每個單字都改,為大寫開頭的駝峰 (upper camel case) 命名。
* … 每個單字除了第一個單字不改,
則為小寫開頭的駝峰 (lower camel case) 命名。
4. 最後,將所有單字連成一個識別符。
需要注意的是,這邊的大小寫幾乎是已經無視原來的單字。範例:
- “XML HTTP request”
* 正確:XmlHttpRequest
* 錯誤:XMLHTTPRequest
- “new customer ID”
* 正確:newCustomerId
* 錯誤:newCustomerID
- “inner stopwatch”
* 正確:innerStopwatch
* 錯誤:innerStopWatch
- “supports IPv6 on iOS?”
* 正確:supportsIpv6OnIos
* 錯誤:supportsIPv6OnIOS
- “YouTube importer”
* 正確:YouTubeImporter 或 YoutubeImporter *****
*允許, 但不建議。
> **Note:**
> 有些字在英語中,有無帶著連字符號都沒有錯,
> 舉例來說「nonempty」以及「non-empty」二者皆對,
> 所以方法若是命名成 `checkNonempty` 以及 `checkNonEmpty` 都是正確的。
6. 程式碼慣例(Programming Practices)
=====================================
6.1 @Override:一定要使用 (always used)
----------------------------------------
當一個被合法的標註了 `@Override` 的方法(method),
他一定是覆寫了其父類別 (superclass) 的方式、
實作了介面方法(interface mthod)
以及介面中重新指定了其父介面 (superinterface) 的方法。
例外: `@Override` 當可以被省略時,
代表其父類別的方法已被標示為 `@Deprecated`
6.2 補獲異常:不可忽視 (Caught exceptions: not ignored)
-------------------------------------------------------
異常 (Except) 如下所述,他是少數在發生異常時,
可以不做回應的異常處理。
(以標準的異常回應,是需要記錄下來的,
或若是被視為「不可能(impoosible)」時,
則重新用 `AssertionError` 拋出。
當在 catch 區塊中,確實沒有任何動作的話,便用註解明確的說明其原委。
try {
int i = Integer.parseInt(response);
return handleNumericResponse(i);
} catch (NumberFormatException ok) {
// it's not numeric; that's fine, just continue
}
return handleTextResponse(response);
例外:在測試中,若其 catch 的異常被命名為 `expected` ,
則其註解可以被省略。
下方這是一個常見的狀況,用以確保在測試時會拋出期望中的異常,
所以這邊是不需要註解的。
try {
emptyStack.pop();
fail();
} catch (NoSuchElementException expected) {
}
6.3 靜態成員:適當的搭配類別用 (Static members: qualified using class)
----------------------------------------------------------------------
引用靜態成員必需搭配著類別 (class) 名稱才是適當的用法,
不是和一個物件類型或是描述句來使用。
Foo aFoo = ...;
Foo.aStaticMethod(); // 好
aFoo.aStaticMethod(); // 不好
somethingThatYieldsAFoo().aStaticMethod(); // 非常糟
6.4 Finalize 不要使用 (Finalizers: not used)
---------------------------------------------
`Object.finalize` 一個極為罕用到的覆寫方法。
> **Tip:**
> 不要用他。若非用不可時,
> 請先閱讀並確實理解 [Effective Java] 的第七項:「Avoid Finalizers,」
> 務必留心,並別這麼做。
[Effective Java]: https://www.google.com/search
?hl=zh-TW&tbo=p&tbm=bks&q=isbn:8131726592
7. Javadoc
==========
7.1 格式 (Formatting)
----------------------
### 7.1.1 通用格式 (General form) ###
即本的 Javadoc 區塊格式如下範例:
/**
* Multiple lines of Javadoc text are written here,
* wrapped normally...
*/
public int method(String p1) { ... }
只有單行的範例:
/** An especially short bit of Javadoc. */
這是個永遠可以被接受的基本格式。
當整個 Javadoc (包含註解) 沒用使用到 at-子句時,
若是可以被容量在一行的話,就採用單行的格式。
### 7.1.2 段落 (Paragraphs) ###
空行-在段落之間,以星號(*) 為起始的一行空白;
若是有「at-子句」,就要將之擺在這個群組之前。
若是每個段落在一開始有 <p> 時,他跟第一個字之間不會有空格。
### 7.1.3 At-子句 (At-clauses) ###
當全部的「at-子句 」都出現時,其標準的使用順序為
`@param` 、 `@return` 、 `@throws` 、 `@deprecated` ,
而這四種類型都不會為空。
當一個「at-子句」無法以單行描述完畢時,
其續行該要以 @ 為基準做四個(或更多)空白的縮排。
7.2 摘要片段 (The summary fragment)
------------------------------------
每個類別 (class) 以及成員 (member) 的 Javadoc,
都先以簡潔的摘要片段做為開始。
這個片段非常地重要:在某些狀況下,他會是該類別 (class)
或是 方法 (method) 索引中,唯一出現的文字片段。
片段 - 一個名詞片語或是動詞片語,不是一個完整的句子。
他不會是這麼開始「 A {@code Foo} is a …」,
或是「 This method returns …」,
也不會是一個完整祈使句「Save the record …」。
然而,因為開頭大寫與標點符號的關該,讓片段看起來就像是一個完整的句子。
> **Tip:**
> 舉一個 Javadoc 格式中錯用符號為例 /** @return the customer ID */。
> 這需要被修正成 /** Returns the customer ID. */
7.3 在哪裡使用 Javadoc (Where Javadoc is used)
-----------------------------------------------
在最小的限度下,所有公開類別 (public class)
以及每個類別 (class) 中公開 (public) 或被保護的(protected) 成員
都該寫上 Javadoc,當然也有少數如下列出的例外狀況。
若是被拿來做為定義類別 (class)、方法 (method) 或是屬性 (field)
在實作時該有的整體目的或是行為,
就該寫上註解 (comment) 而非 Javadoc。
(這樣做將更趨一致性並更讓工具看起來親切些 (tool-friendly))。
> **譯注:**
> tool-friendly 不知道怎麼翻譯比較好,所以就用比較直白的陳述表達了。
### 7.3.1 例外:不言自明的方法 (Exception: self-explanatory methods) ###
有些「簡單、明確」的方法也不一定要寫上 Javadoc,
像是 getFoo 這種簡明的案例,好像除了寫上「返回 foo 值」也什麼好寫的。
> Important:
> 當今天是一個必需要讓看的人知道的狀況下,
> 這個例外就不該拿出來做為忽略不寫相關資訊的理由。
> 比方說,有一個方法被命名為 `getCanonicalName`,
> 這種狀況下,看得人可能並不了解「canonical name」這是什麼意思,
> 在這種狀況下就不要忽略它的說明(包含只寫上「返回 canonical name」)。
### 7.3.2 例外:覆寫 (Exception: overrides) ###
在子物中覆寫的父類別的方法就不一定要寫上 Javadoc。
----------
本篇採用創用 CC 姓名標示-非商業性-禁止改作 3.0 台灣 授權條款授權,
如欲轉載請記得註明轉自「[莫希爾(Mosil) 手札][1]」
[1]: http://blog.mosil.biz/2014/05/java-style-guide/
--
錢鍾書: 說出來的話
http://www.psmonkey.org
比不上不說出來的話
Java 版 cookcomic 版
只影射著說不出來的話
and more......
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 60.250.11.98
※ 文章網址: http://www.ptt.cc/bbs/Translate-CS/M.1400476425.A.F83.html
推
06/19 19:59, , 1F
06/19 19:59, 1F
推
07/22 17:10, , 2F
07/22 17:10, 2F
Translate-CS 近期熱門文章
PTT數位生活區 即時熱門文章