File Organization (文件组织)
一个文件应由空行和标识每个节的可选的注释构成
超过2000行的文件难以浏览应被避免
Java source files (Java源文件)
每个Java源文件都包括一个单一的public 类或接口,当private类和接口和public类相联系,你可以将他们放在相同的源文件中。public类必须是这个文件中的第一个类或接口。
Java源文件还有以下顺序:
- 开始的注释
- 包和引入语句
- 类和接口声明
Beginning Comments (开始的注释)
所有源文件都应该以一个C语言类型的注释开始,注释包括程序名称(programmers),日期(data),版本信息(version),版权声明(Copyright notice),程序功能的简短介绍
/*
* Classname
*
* Version infomation
*
* Data
*
* Copyright notice
*
*/
Package and import Statements (包和引入语句)
大多数Java源文件的第一个非注释行都是包声明语句。之后是import引入语句。
例如:
package circularOrbit;
import java.io.BufferedReader;
Class and Interface Declarations(类和接口声明)
部分类/接口声明 | 注解 |
---|---|
文档注释(/** … */) | 文档注解 |
类或接口的语句 | |
类或接口的重写注释 (/* … */) | 该注释包括类或接口的不适合出现在文档注释中的任意信息 |
类的(static)变量 | public, protected,private |
类型变量 | public, protected,private |
构造器 | |
方法 | 这些方法应该按功能而不是按范围或可访问性分组。例如,私有类方法可以位于两个public 实例方法之间。目的是使代码的阅读和理解更加容易。 |
Indentation (缩进排版)
4个空格常被作为缩进排版的一个单位。缩进的形式并未具体指定(空格 vs. 制表符)。一个制表符便是8个空格(而非4个)
Line Length (行的长度)
避免一行的长度超过80个字符,因为他们不能被许多终端和工具处理。
Note:文档中的例子应当应用更短的行长,长度一般不超过70个字符
Wrapping Lines (换行)
当一个表达式无法容纳在一行内时,可以根据如下一般规矩断开:
- 在逗号后断开
- 在一个操作符前断开
- 宁可选择高级别的断开,也不要低级别的断开
- 新的一行应当与上一行同一级别表达式的开首处对齐
- 若是以上规矩导致你的代码杂沓或者使你的代码都堆挤在右边,那就代之以缩进8个空格
函数调用的换行栗子:
function(longExpression1, longExpression2, longExpression3,
longExpression4, longExpression5);
var = function1(longExpression1,
function2(longExpression2,
longExpression3));
数学表达式的换行栗子:前者更好,因为断开处位于括号表达式的外边,这是个较高等级断开。
longName1 = longName2 * (longName3 + longName4 - longName5)
+ 4 * longname6; // PREFER
longName1 = longName2 * (longName3 + longName4
- longName5) + 4 * longname6; // AVOID
方法声明的换行栗子:第一个是常规情形,第二个采用缩进8个空格,否则使其过于靠右
//CONVENTIONAL INDENTATION
someMethod(int anArg, Object anotherArg, String yetAnotherArg,
Object andStillAnother) {
...
}
//INDENT 8 SPACES TO AVOID VERY DEEP INDENTS
private static synchronized horkingLongMethodName(int anArg,
Object anotherArg, String yetAnotherArg,
Object andStillAnother) {
...
}
对于if语句的换行栗子:(通常采用8空格规则,4空格阅读困难)
//DON’T USE THIS INDENTATION
if ((condition1 && condition2)
|| (condition3 && condition4)
||!(condition5 && condition6)) { //BAD WRAPS
doSomethingAboutIt(); //MAKE THIS LINE EASY TO MISS
}
//USE THIS INDENTATION INSTEAD
if ((condition1 && condition2)
|| (condition3 && condition4)
||!(condition5 && condition6)) {
doSomethingAboutIt();
}
//OR USE THIS
if ((condition1 && condition2) || (condition3 && condition4)
||!(condition5 && condition6)) {
doSomethingAboutIt();
}
处理三元表达式的栗子:
alpha = (aLongBooleanExpression) ? beta : gamma;
alpha = (aLongBooleanExpression) ? beta
: gamma;
alpha = (aLongBooleanExpression)
? beta
: gamma;
Comments (注释)
Java程序有两类注释:实现注释(implementation comments)和文档注释(document comments)。实现注释是那些在C++中见过的,应用/…/和//界定的注释。文档注释(被称为"doc comments")是Java独有的,并由/**…*/界定。文档注释可以经由过程javadoc对象转换成HTML文件。
实现注释用以注释代码或者实现细节。文档注释从实现(implementation-free)的角度描述代码的规范。它可以被那些手头没有源码的开辟人员读懂。
注释应被用来给出代码的总括,并供给代码自身没有供给的附加信息。注释应当仅包含与浏览和懂得程序有关的信息。例如,响应的包如何被建树或位于哪个目次下之类的信息不该包含在注释中。
在注释里,对设计决定计划中首要的或者不是显而易见的处所进行申明是可以的,但应避免供给代码中己清楚表达出来的反复信息。多余的的注释很轻易过期。凡是应避免那些代码更新就可能过期的注释。
Note:频繁的注释有时反应出代码的低质量。当你感觉被迫要加注释的时辰,推敲一下重写代码使其更清楚。
注释不该写在用星号或其他字符画出来的大框里。注释不该包含诸如制表符和回退符之类的特别字符
Implementation Comment Formats
程序可以有4种实现注释的风格:块(block)、单行(single-line)、尾端(trailing)和行末(end-of-line)。
Block Comments (块注释)
block comments 用于描述文件,方法,数据结构和算法。block comments 通常被放置在每个文件和方法的开头,也可用于方法内部。功能和办法内部的块注释应当和它们所描述的代码具有一样的缩进格局。
块注释之首应当有一个空行,用于把块注释和代码分别开来 ,举个栗子:
/*
* comments
*/
块注释可以以/*-开始,indent(1)就可以将之辨认为一个代码块的开端,而不会重排它
/*
* Here is a block comment with some very special
* formatting that I want indent(1) to ignore.
*
* one
* two
* three
*/
Note:如果不使用indent(1),就不必在代码中添加/*-
Single-Line Comments (单行注释)
短注释可以显示在一行内,并与其后的代码具有一样的缩进层级。若是一个注释不能在一行内写完,就该采取块注释(拜见"块注释")。单行注释之前应当有一个空行。以下是一个Java代码中单行注释的例子:
if (condition) {
/* Handle the condition. */
...
}
Trailing Comments (尾端注释)
极短的注释可以与它们所要描述的代码位于同一行,然则应当有足够的空白来分隔代码和注释。如有多个短注释呈现于代码片段中,它们应当具有相同的缩进。避免使用汇编语言风格,即用尾随注释注释每行可执行代码。
if (a == 2) {
return TRUE; /* special case */
} else {
return isprime(a); /* works only for odd a */
}
End-Of-Line Comments(行尾注释)
注释界定符"//",可以注释掉整行或者一行中的一部分。它不应该用于连续的多行文本注释;但是,它可以用于连续的多行代码注释。
三种使用风格:
if (foo > 1) {
// Do a double-flip.
...
}
else
return false; // Explain why here.
//if (bar > 1) {
//
// // Do a triple-flip.
// ...
//}
//else
// return false;
Documentation Comments (文档注释)
文档注释描述Java的类、接口、构造器,方法,以及字段(field)。每个文档注释都被置于注释定界符/**…*/之中,一个注释对应一个类、接口或成员。
关于类的实现应该在这样的实现块注释中进行,在class语句之后,而不是在class doc注释中。文档注释不应放置在方法或构造函数定义块内,因为Java将文档注释与注释后的第一个声明关联起来。
Declarations (声明)
Number Per Line(每行声明变量的数量)
推荐每个变量在单独的一行声明,而不是同一声明,有利于写注释
int level;
int size;
is better than
int level,size;
Note:以上栗子中变量的类型和名称中间间隔了一个空格,间隔一个tabs也是ok的。
Placement (布局)
在代码块的开端处放置声明,不要等到使用变量时才将其声明。
void myMethod() {
int int1 = 0; // beginning of method block
if (condition) {
int int2 = 0; // beginning of "if"block
...
}
}
一个例外是循环中的标签变量
for (int i = 0; i < maxLoops; i++) { ...
避免声明的局部变量覆盖上一级声明的变量。
int count;
...
func() {
if (condition) {
int count; // AVOID!
...
}
...
}
Initialization(初始化)
尽量在声明局部变量的同时初始化。除非变量的初始值依附于某些先前产生的值。
Class and Interface Declarations(类和接口的声明)
当编写类和接口时,应当遵守以下规范:
- 在方法名与其参数列表之前的左括号"("间不要有空格
- 左大括号"{"位于声明语句同行的末尾
- 右大括号"}“另起一行,与响应的声明语句对齐,除非是一个空语句,”}“应紧跟在”{"之后
- 方法之间以空行分割
Statements(语句)
Simple Statements(简单语句)
每行至多包含一条语句:
argv++ ; argc-- ; //AVOID!
Compound Statements(复合语句)
复合语句是包含在大括号中的语句序列,形如"{ 语句 }"。例如下面各段。
- 被括此中的语句应当较之复合语句缩进一个层次
- 左大括号"{“应位于复合语句首行的行尾;右大括号”}"应另起一行并与复合语句首行对齐
- 大括号可以被用于所有语句,包含单个语句,只要这些语句是诸如if-else或for。这样便于添加语句而无需考虑因为忘了加括号而引入bug。
Return Statements(返回语句)
一个带返回值的return语句不应用小括号"()",除非它们以某种体式格式使返回值更为显见。例如:
return;
return myDisk.size();
return (size ? size : defaultSize);
if , if-else , if-else-if-else Statements
Note:if语句通常使用大括号,应避免如下情况
if (condition) //AVOID! THIS OMITS THE BRACES {}!
statement;
for语句
Note:空的for语句
for (initialization; condition; update);
Switch语句
当一个case块中没有break时,则应在break的位置上加入注释/* falls through */
每个switch语句都应包含一个default部分,在default中的break是多余的,但当新增一个case块时,他会阻止一个 fall-through 错误
while语句,do-while语句,try-catch语句不在赘述
White Space(空白)
Blank Lines (空行)
空行将逻辑相关的代码段分隔开,以增强可读性。
下列情形应当应用两个空行:
- 源文件的两个片段间
- 类或接口的声明之间
下列情形应当应用一个空行:
- 两个方法之间
- 方法中的局部变量与方法的第一条语句之间
- 块注释和单行注释之前
- 一个方法的两个逻辑块之间
Blank Spaces(空格)
下列情景应用空格:
- 紧跟括号的关键字应当被空格分隔 :
while (true)
Note: 空格不能置于方法名和左括号之间。 - 空白应当位于参数列表中逗号的后面
- 所有的二元运算符,除了".",应当应用空格将之与操纵数分隔。一元操纵符和操纵数之间不因该加空格,比如:负号("-")、自增("++")和自减("–")
- for语句中的表达式应当被空格分隔
- 强转后应加空格
myMethod((byte) aNum, (Object) x);
myFunc((int) (cp + 5), ((int) (i + 3))
+ 1);
Naming Conventions(命名规范)
。。此处略去
Programming Practices(编程练习)
Providing Access to Instance and Class Variables(确定权限)
没有把握时,不应把实例后类变量声明为public,实例变量无需显式的设置(set)和获取(gotten),这作为方法调用的边沿效应 (side effect)而产生。一个具有公有实例变量的恰当例子,是类仅作为数据布局,没有行为。亦即,若你要应用一个结构(struct)而非一个类,那么把类的实例变量声明为公有是合适的。
Referring to Class Variables and Methods(对类中变量和方法的引用)
避免使用对象去应用一个类的静态变量或方法。应当使用类名调用。
classMethod(); //OK
AClass.classMethod(); //OK
anObject.classMethod(); //AVOID!
Constants(常量)
数字常量不应被直接写入代码中,除非是-1,0,1,出现在for循环中作为计数器的值。
Variable Assignments(变量赋值)
避免在一个语句中给多个变量赋相同的值
fooBar.fChar = barFoo.lchar = ""c""; // AVOID!
不要在容易与相等运算符混淆的位置使用赋值运算符。
if (c++ = d++) { // AVOID! Java disallows
...
}
if ((c++ = d++) != 0) { //correct
...
}
不要在试图提高运行时性能时使用嵌入的分配。这是编译器的工作,而且,它实际上很少有帮助。
d = (a = b + c) + r; // AVOID!
should be written as
a = b + c;
d = a + r;
Miscellaneous Practices(其他练习)
Parentheses(圆括号)
在涉及混合运算符的表达式中大量使用括号通常是一个好主意,以避免运算符优先级问题。即使在您看来,运算符的优先顺序是明确的,但对于其他人,您也不应该假定其他程序员和您一样了解优先顺序。
if (a == b && c == d) // AVOID!
if ((a == b) && (c == d)) // RIGHT
Returning Values(返回值)
栗子:
//不提倡
if (booleanExpression) {
return TRUE;
} else {
return FALSE;
}
//提倡
return booleanExpression;
类似的:
//不提倡
if (condition) {
return x;
}
return y;
//提倡
return (condition ? x : y);
Expressions before ‘?’ in the Conditional Operator (在条件控制中?前的表达式)
一个包含二元运算符的表达式出现在三元运算符" ? : “的”?"之前,那么应当给表达式添上一对圆括号。例如:
(x >= 0) ? x ; -x;
Special Comments(特殊注释)
在注释中应用XXX来标识某些未实现(bogus)的但可以工作(works)的内容。用FIXME来标识某些假的和错误的内容。