作者PsMonkey (痞子军团团长)
看板Translate-CS
标题[翻译] Google Java 程式风格指南
时间Mon May 19 13:13:42 2014
原文网址:
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://webptt.com/cn.aspx?n=bbs/Translate-CS/M.1400476425.A.F83.html
1F:推 RfTV:帮推!辛苦了! 06/19 19:59
2F:推 jackyamato:辛苦了!!非常有用!! 07/22 17:10