Google 出品的 Java 编码规范,权威又科学,强烈推荐
4.6.2 水平空白
除了语言需求和其它规则,并且除了文字,注释和 Javadoc 用到单个空格,单个 ASCII 空格也出现在以下几个地方:
分隔任何保留字与紧随其后的左括号( ()(如 if,forcatch 等)。
分隔任何保留字与其前面的右大括号( })(如 else,catch)。
在任何左大括号前( {),两个例外:
@SomeAnnotation({a,b})(不使用空格)。 String[][]x=foo;(大括号间没有空格,见下面的 Note)。
在任何二元或三元运算符的两侧。这也适用于以下“类运算符”符号:
类型界限中的 &( <TextendsFoo&Bar>)。
catch 块中的管道符号( catch(FooException|BarExceptione)。 foreach 语句中的分号。
在 ,:;及右括号( ))后
如果在一条语句后做注释,则双斜杠(//)两边都要空格。这里可以允许多个空格,但没有必要。
类型和变量之间: List<string>list。</string>
数组初始化中,大括号内的空格是可选的,即 newint[]{5,6}和 newint[]{5,6}都是可以的。
Note:这个规则并不要求或禁止一行的开关或结尾需要额外的空格,只对内部空格做要求。
4.6.3 水平对齐:不做要求
术语说明:水平对齐指的是通过增加可变数量的空格来使某一行的字符与上一行的相应字符对齐。
这是允许的(而且在不少地方可以看到这样的代码),但 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 的工作并且可能导致更多的合并冲突。
4.7 用小括号来限定组:推荐
除非作者和 reviewer 都认为去掉小括号也不会使代码被误解,或是去掉小括号能让代码更易于阅读,否则我们不应该去掉小括号。 我们没有理由假设读者能记住整个 Java 运算符优先级表。
4.8 具体结构
4.8.1 枚举类
枚举常量间用逗号隔开,换行可选。
没有方法和文档的枚举类可写成数组初始化的格式:
private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }
由于枚举类也是一个类,因此所有适用于其它类的格式规则也适用于枚举类。
4.8.2 变量声明
4.8.2.1 每次只声明一个变量
不要使用组合声明,比如 inta,b;。
4.8.2.2 需要时才声明,并尽快进行初始化
不要在一个代码块的开头把局部变量一次性都声明了(这是 c 语言的做法),而是在第一次需要使用它时才声明。 局部变量在声明时最好就进行初始化,或者声明后尽快进行初始化。
4.8.3 数组
4.8.3.1 数组初始化:可写成块状结构
数组初始化可以写成块状结构,比如,下面的写法都是 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}
4.8.3.2 非 C 风格的数组声明
中括号是类型的一部分: String[]args, 而非 Stringargs[]。
4.8.4 switch 语句
术语说明:switch 块的大括号内是一个或多个语句组。每个语句组包含一个或多个 switch 标签( caseFOO:或 default:),后面跟着一条或多条语句。
4.8.4.1 缩进
与其它块状结构一致,switch 块中的内容缩进为 2 个空格。
每个 switch 标签后新起一行,再缩进 2 个空格,写下一条或多条语句。
4.8.4.2 Fall-through:注释
在一个 switch 块内,每个语句组要么通过 break,continue,return 或抛出异常来终止,要么通过一条注释来说明程序将继续执行到下一个语句组, 任何能表达这个意思的注释都是 OK 的(典型的是用 // fall through)。这个特殊的注释并不需要在最后一个语句组(一般是 default)中出现。示例:
switch (input) {
case 1:
case 2:
prepareOneOrTwo();
// fall through
case 3:
handleOneTwoOrThree();
break;
default:
handleLargeNumber(input);
}
4.8.4.3 default 的情况要写出来
每个 switch 语句都包含一个 default 语句组,即使它什么代码也不包含。
4.8.5 注解(Annotations)
注解紧跟在文档块后面,应用于类、方法和构造函数,一个注解独占一行。这些换行不属于自动换行(第 4.5 节,自动换行),因此缩进级别不变。例如:
@Override
@Nullable
public String getNameIfPresent() { ... }
例外:单个的注解可以和签名的第一行出现在同一行。例如:
@Override public int hashCode() { ... }
应用于字段的注解紧随文档块出现,应用于字段的多个注解允许与字段出现在同一行。例如:
@Partial @Mock DataLoader loader;
参数和局部变量注解没有特定规则。
4.8.6 注释
4.8.6.1 块注释风格
块注释与其周围的代码在同一缩进级别。它们可以是 / ... /风格,也可以是 // ...风格。对于多行的 / ... /注释,后续行必须从 开始, 并且与前一行的 对齐。以下示例注释都是 OK 的。
/*
This is // And so /* Or you can
okay. // is this. * even do this. */
*/
注释不要封闭在由星号或其它字符绘制的框架里。
Tip:在写多行注释时,如果你希望在必要时能重新换行(即注释像段落风格一样),那么使用 / ... /。
4.8.7 Modifiers
类和成员的 modifiers 如果存在,则按 Java 语言规范中推荐的顺序出现。
public protected private abstract static final transient volatile synchronized native strictfp
命名约定
5.1 对所有标识符都通用的规则
标识符只能使用 ASCII 字母和数字,因此每个有效的标识符名称都能匹配正则表达式 \w+。
在 Google 其它编程语言风格中使用的特殊前缀或后缀,如 name_, mName, s_name 和 kName,在 Java 编程风格中都不再使用。
5.2 标识符类型的规则
5.2.1 包名
包名全部小写,连续的单词只是简单地连接起来,不使用下划线。
5.2.2 类名
类名都以 UpperCamelCase 风格编写。
类名通常是名词或名词短语,接口名称有时可能是形容词或形容词短语。现在还没有特定的规则或行之有效的约定来命名注解类型。
测试类的命名以它要测试的类的名称开始,以 Test 结束。例如, HashTest 或 HashIntegrationTest。
5.2.3 方法名
方法名都以 lowerCamelCase 风格编写。
方法名通常是动词或动词短语。
下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。一个典型的模式是: test<MethodUnderTest>_<state>,例如 testPop_emptyStack。 并不存在唯一正确的方式来命名测试方法。
5.2.4 常量名
常量名命名模式为 CONSTANT_CASE,全部字母大写,用下划线分隔单词。那,到底什么算是一个常量?
每个常量都是一个静态 final 字段,但不是所有静态 final 字段都是常量。在决定一个字段是否是一个常量时, 考虑它是否真的感觉像是一个常量。例如,如果任何一个该实例的观测状态是可变的,则它几乎肯定不会是一个常量。 只是永远不 打算改变对象一般是不够的,它要真的一直不变才能将它示为常量。
// Constants
static final int NUMBER = 5;
static final ImmutableList<String> NAMES = ImmutableList.of("Ed", "Ann");
static final Joiner COMMA_JOINER = Joiner.on(','); // because Joiner is immutablestatic 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 Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};
这些名字通常是名词或名词短语。
5.2.5 非常量字段名
非常量字段名以 lowerCamelCase 风格编写。
这些名字通常是名词或名词短语。
5.2.6 参数名
参数名以 lowerCamelCase 风格编写。
参数应该避免用单个字符命名。
5.2.7 局部变量名
局部变量名以 lowerCamelCase 风格编写,比起其它类型的名称,局部变量名可以有更为宽松的缩写。
虽然缩写更宽松,但还是要避免用单字符进行命名,除了临时变量和循环变量。
即使局部变量是 final 和不可改变的,也不应该把它示为常量,自然也不能用常量的规则去命名它。
5.2.8 类型变量名
类型变量可用以下两种风格之一进行命名:
单个的大写字母,后面可以跟一个数字(如:E, T, X, T2)。
以类命名方式(5.2.2 节),后面加个大写的 T(如:RequestT, FooBarT)。
5.3 驼峰式命名法(CamelCase)
驼峰式命名法分大驼峰式命名法( UpperCamelCase)和小驼峰式命名法( lowerCamelCase)。 有时,我们有不只一种合理的方式将一个英语词组转换成驼峰形式,如缩略语或不寻常的结构(例如”IPv6”或”iOS”)。Google 指定了以下的转换方案。
名字从 散文形式(prose form)开始:
把短语转换为纯 ASCII 码,并且移除任何单引号。例如:”Müller’s algorithm”将变成”Muellers algorithm”。
把这个结果切分成单词,在空格或其它标点符号(通常是连字符)处分割开。
推荐:如果某个单词已经有了常用的驼峰表示形式,按它的组成将它分割开(如”AdWords”将分割成”ad words”)。 需要注意的是”iOS”并不是一个真正的驼峰表示形式,因此该推荐对它并不适用。
现在将所有字母都小写(包括缩写),然后将单词的第一个字母大写:
每个单词的第一个字母都大写,来得到大驼峰式命名。
除了第一个单词,每个单词的第一个字母都大写,来得到小驼峰式命名。
最后将所有的单词连接起来得到一个标识符。
示例:
Prose form Correct Incorrect
"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.1 @Override:能用则用
只要是合法的,就把 @Override 注解给用上。
6.2 捕获的异常:不能忽视
除了下面的例子,对捕获的异常不做响应是极少正确的。(典型的响应方式是打印日志,或者如果它被认为是不可能的,则把它当作一个 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);
例外:在测试中,如果一个捕获的异常被命名为 expected,则它可以被不加注释地忽略。下面是一种非常常见的情形,用以确保所测试的方法会抛出一个期望中的异常, 因此在这里就没有必要加注释。
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
。
Tip:不要使用 finalize。如果你非要使用它,请先仔细阅读和理解 Effective Java 第 7 条款:“Avoid Finalizers”,然后不要使用它。
Javadoc
7.1 格式
7.1.1 一般形式
Javadoc 块的基本格式如下所示:
/**
Multiple lines of Javadoc text are written here,
wrapped normally...
*/
public int method(String p1) { ... }
《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】
或者是以下单行形式:
/** An especially short bit of Javadoc. */
基本格式总是 OK 的。当整个 Javadoc 块能容纳于一行时(且没有 Javadoc 标记 @XXX),可以使用单行形式。
7.1.2 段落
空行(即,只包含最左侧星号的行)会出现在段落之间和 Javadoc 标记(@XXX)之前(如果有的话)。 除了第一个段落,每个段落第一个单词前都有标签 <p>,并且它和第一个单词间没有空格。
7.1.3 Javadoc 标记
标准的 Javadoc 标记按以下顺序出现: @param, @return, @throws, @deprecated, 前面这 4 种标记如果出现,描述都不能为空。 当描述无法在一行中容纳,连续行需要至少再缩进 4 个空格。
7.2 摘要片段
每个类或成员的 Javadoc 以一个简短的摘要片段开始。这个片段是非常重要的,在某些情况下,它是唯一出现的文本,比如在类和方法索引中。
这只是一个小片段,可以是一个名词短语或动词短语,但不是一个完整的句子。它不会以 A{@codeFoo}isa...或 Thismethod returns...开头, 它也不会是一个完整的祈使句,如 Savethe record...。然而,由于开头大写及被加了标点,它看起来就像是个完整的句子。
Tip:一个常见的错误是把简单的 Javadoc 写成 /* @return the customer ID /,这是不正确的。它应该写成 /* Returns the customer ID. /。
7.3 哪里需要使用 Javadoc
至少在每个 public 类及它的每个 public 和 protected 成员处使用 Javadoc,以下是一些例外:
评论