术语说明:块状结构(block-like construct)指的是一个类,方法或构造函数的主体。需要注意的是,数组初始化中的初始值可被选择性地视为块状结构(4.8.3.1节)。
大括号与if, else, for, do, while
语句一起使用,即使只有一条语句(或是空),也应该把大括号写上。
对于非空块和块状结构,大括号遵循Kernighan和Ritchie风格 (Egyptian brackets):
示例:
return new MyClass() {
@Override public void method() {
if (condition()) {
try {
something();
} catch (ProblemException e) {
recover();
}
}
}
};
4.8.1节给出了enum类的一些例外。
一个空的块状结构里什么也不包含,大括号可以简洁地写成{}
,不需要换行。例外:如果它是一个多块语句的一部分(if/else 或 try/catch/finally) ,即使大括号内没内容,右大括号也要换行。
示例:
void doNothing() {}
每当开始一个新的块,缩进增加2个空格,当块结束时,缩进返回先前的缩进级别。缩进级别适用于代码和注释。(见4.1.2节中的代码示例)
每个语句后要换行。
一个项目可以选择一行80个字符或100个字符的列限制,除了下述例外,任何一行如果超过这个字符数限制,必须自动换行。
例外:
package
和import
语句(见3.2节和3.3节)。术语说明:一般情况下,一行长代码为了避免超出列限制(80或100个字符)而被分为多行,我们称之为自动换行(line-wrapping)。
我们并没有全面,确定性的准则来决定在每一种情况下如何自动换行。很多时候,对于同一段代码会有好几种有效的自动换行方式。
Tip: 提取方法或局部变量可以在不换行的情况下解决代码过长的问题(是合理缩短命名长度吧)
自动换行的基本准则是:更倾向于在更高的语法级别处断开。
非赋值运算符
处断开,那么在该符号前断开(比如+,它将位于下一行)。注意:这一点与Google其它语言的编程风格不同(如C++和JavaScript)。 这条规则也适用于以下“类运算符”符号:点分隔符(.),类型界限中的&(<T extends Foo & Bar>
),catch块中的管道符号(catch (FooException | BarException e
)赋值运算符
处断开,通常的做法是在该符号后断开(比如=,它与前面的内容留在同一行)。这条规则也适用于foreach
语句中的分号。自动换行时,第一行后的每一行至少比第一行多缩进4个空格(注意:制表符不用于缩进。见2.3.1节)。
当存在连续自动换行时,缩进可能会多缩进不只4个空格(语法元素存在多级时)。一般而言,两个连续行使用相同的缩进当且仅当它们开始于同级语法元素。
第4.6.3水平对齐一节中指出,不鼓励使用可变数目的空格来对齐前面行的符号。
以下情况需要使用一个空行:
多个连续的空行是允许的,但没有必要这样做(我们也不鼓励这样做)。
除了语言需求和其它规则,并且除了文字,注释和Javadoc用到单个空格,单个ASCII空格也出现在以下几个地方:
(
)(如if, for catch
等)。}
)(如else, catch
)。{
),两个例外:@SomeAnnotation({a, b})
(不使用空格)。String[][] x = foo;
(大括号间没有空格,见下面的Note)。<T extends Foo & Bar>
)。catch (FooException | BarException e
)。foreach
语句中的分号。, : ;
及右括号()
)后new int[] {5, 6}
和new int[] { 5, 6 }
都是可以的。Note:这个规则并不要求或禁止一行的开关或结尾需要额外的空格,只对内部空格做要求。
术语说明:水平对齐指的是通过增加可变数量的空格来使某一行的字符与上一行的相应字符对齐。
这是允许的(而且在不少地方可以看到这样的代码),但Google编程风格对此不做要求。即使对于已经使用水平对齐的代码,我们也不需要去保持这种风格。
以下示例先展示未对齐的代码,然后是对齐的代码:
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
Tip:对齐可增加代码可读性,但它为日后的维护带来问题。考虑未来某个时候,我们需要修改一堆对齐的代码中的一行。 这可能导致原本很漂亮的对齐代码变得错位。很可能它会提示你调整周围代码的空白来使这一堆代码重新水平对齐(比如程序员想保持这种水平对齐的风格), 这就会让你做许多的无用功,增加了reviewer的工作并且可能导致更多的合并冲突。
除非作者和reviewer都认为去掉小括号也不会使代码被误解,或是去掉小括号能让代码更易于阅读,否则我们不应该去掉小括号。 我们没有理由假设读者能记住整个Java运算符优先级表。
枚举常量间用逗号隔开,换行可选。
没有方法和文档的枚举类可写成数组初始化的格式:
private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }
由于枚举类也是一个类,因此所有适用于其它类的格式规则也适用于枚举类。
不要使用组合声明,比如int a, b;
。
不要在一个代码块的开头把局部变量一次性都声明了(这是c语言的做法),而是在第一次需要使用它时才声明。 局部变量在声明时最好就进行初始化,或者声明后尽快进行初始化。
数组初始化可以写成块状结构,比如,下面的写法都是OK的:
new int[] {
0, 1, 2, 3
}
new int[] {
0,
1,
2,
3
}
new int[] {
0, 1,
2, 3
}
new int[]{0, 1, 2, 3}
中括号是类型的一部分:String[] args
, 而非String args[]
。
术语说明:switch块的大括号内是一个或多个语句组。每个语句组包含一个或多个switch标签(case FOO:
或default:
),后面跟着一条或多条语句。
与其它块状结构一致,switch块中的内容缩进为2个空格。
每个switch标签后新起一行,再缩进2个空格,写下一条或多条语句。
在一个switch块内,每个语句组要么通过break, continue, return
或抛出异常来终止,要么通过一条注释来说明程序将继续执行到下一个语句组, 任何能表达这个意思的注释都是OK的(典型的是用// fall through
)。这个特殊的注释并不需要在最后一个语句组(一般是default
)中出现。示例:
switch (input) {
case 1:
case 2:
prepareOneOrTwo();
// fall through
case 3:
handleOneTwoOrThree();
break;
default:
handleLargeNumber(input);
}
每个switch语句都包含一个default
语句组,即使它什么代码也不包含。
注解紧跟在文档块后面,应用于类、方法和构造函数,一个注解独占一行。这些换行不属于自动换行(第4.5节,自动换行),因此缩进级别不变。例如:
@Override
@Nullable
public String getNameIfPresent() { ... }
例外:单个的注解可以和签名的第一行出现在同一行。例如:
@Override public int hashCode() { ... }
应用于字段的注解紧随文档块出现,应用于字段的多个注解允许与字段出现在同一行。例如:
@Partial @Mock DataLoader loader;
参数和局部变量注解没有特定规则。
块注释与其周围的代码在同一缩进级别。它们可以是/* ... */
风格,也可以是// ...
风格。对于多行的/* ... */
注释,后续行必须从*
开始, 并且与前一行的*
对齐。以下示例注释都是OK的。
/*
* This is // And so /* Or you can
* okay. // is this. * even do this. */
*/
注释不要封闭在由星号或其它字符绘制的框架里。
Tip:在写多行注释时,如果你希望在必要时能重新换行(即注释像段落风格一样),那么使用
/* ... */
。
类和成员的modifiers如果存在,则按Java语言规范中推荐的顺序出现。
public protected private abstract static final transient volatile synchronized native strictfp