首页

Java语言代码规范《Code Conventions for the JavaTM Programming Language》中文译文

标签:java代码规范,命名规范,命名规则     发布时间:2017-11-26   

一、介绍

为什么需要代码规范 - 由于以下几个原因,使得代码规范对开发者来说显得重要: 

1) 80%的项目生命期处于维护阶段。@b@2) 几乎所有的软件都不是由最初的作者在进行维护。 @b@3) 代码规范改善了软件可读性,允许更快、更彻底的理解新代码。 @b@4) 如果在产品中使用了您的源代码,您需要确信代码对产品来说是封装良好的。

二、文件命名

本节是列出了文件扩展名和文件命名的一般性习惯。

2.1 文件扩展名 - JAVA软件使用以下文件扩展名: 

文件类型

扩展名

Java源程序

.java

Java字节码

.class

2.2 文件命名 - 经常使用的文件名称有: 

文件名

用途

GNUmakefile

Makefiles首选名称. 我们使用gnumake来构建软件.

README

Readme文件首选名称。

2.3 文件组织 - 组成文件的段落应当用空行分开,并且可以使用注释将每个段落标识出来。 超过2000行的文件会显示臃肿,因此应当尽量避免。 

三、JAVA源文件

每一个Java源文件包含一个公共的类或者接口。当私有的类和接口与这个公共的类和接口关联时,您可以将它们放到相同的文件中。公共类和接口应当是文件中的第一个类或者接口。在下面几个访问存在注释

1)文件开始处的注释 (参见 "开始注释")      @b@2)包和导入定义@b@3)类和接口定义 (参见 "类和接口定义")

3.1 开始注释 - 所有的源文件都应该以一个C风格的注释开始,注释中应当列出类名,版本信息,日期和版权声明: 

/*@b@ * 类名@b@ * @b@ * 版本信息@b@ *@b@ * 日期@b@ * @b@ * 版权声明@b@ */

3.2 包和导入声明 - 绝大多数JAVA源文件的第一个非注释行是package语句。之后, import 语句出现。如:

package java.awt;@b@import java.awt.peer.CanvasPeer;@b@@b@//提示: 唯一包名的第一部分总是以全小写ASCII 字符书写,并且应当是顶级域名,通常是com, edu, gov, mil, net, org或者两位由@b@//英文字母标识的国家代码。国家代码由ISO Standard 3166, 1981规范指定(译者注:如中国的国家代码为cn)。

3.3 类和接口定义 - 下表描述了接口和类定义,定义的样式请参见"Java代码示例". 

类和接口定义

备注

1

类/接口文档注释 (/**...*/)

参见 "文档注释".

2

Class或者interface 声明

3

如果有必要,对类/接口编写实现注释 (/*...*/)

该注释应当包含任何接口/类信息,这些信息不适合在类/接口文档注释中出现。

4

类 (静态)变量

首先是公共类变量,其次是保护变量,其次是包级别变量 (无访问修饰符),   最后是私有变量.

5

实例变量

首先是公共实例变量,其次是保护变量,其次是包级别变量 (无访问修饰符), 最后是私有变量.

6

构造器

7

方法

以功能对这些方法分组比以作用域或者可访问性分组更适当. 例如, 一个私有的类方法可以在公共的实例方法之间. 其目的是使阅读和理解代码更容易.

四、缩排

缩排应当以四个空格为单位. 没有强制的缩排规定 (空格vs. tabs)(译者注:这是java语言规范中定义的,在大多数的项目中,均规定以四个空格为缩排单位而不是tabs)。Tabs必须被设置为八个空格 (而不是四个). 

4.1 行宽 - 避免每行超过80字符,因为超过部分不会被许多终端或者工具处理。 注意: 文档中使用的例子应当更短,一般不要超过70个字符. 

4.2 折行 - 当一个表达式不能在一行中书写完毕时,通过以下方式折行: 

在“,”后面折行. @b@在一个操作符前折行. @b@以代码层次高低决定折行,层次高的代码在同一行. @b@同一层次的代码左边对齐. @b@如果上一规则使代码变得不清晰,则统一都缩排8个空格.

以下是一些方法调用折行的示例: 

someMethod(longExpression1, longExpression2, longExpression3, @b@        longExpression4, longExpression5);@b@ @b@var = someMethod1(longExpression1,@b@                someMethod2(longExpression2,@b@                        longExpression3));

以下是两个算术表达式折行的例子. 第一个例子是推荐的, 因为折行发生在()外面。

longName1 = longName2 * (longName3 + longName4 - longName5)@b@           + 4 * longname6; // 更好的@b@ @b@longName1 = longName2 * (longName3 + longName4@b@                       - longName5) + 4 * longname6; // 应当避免的

以下是两个过程定义的折行例子。第一个是常规的选择.第二个例子应该将第二行和第三行右移, 一般的,应当以8个空格进行缩排. 

//常规的缩排@b@someMethod(int anArg, Object anotherArg, String yetAnotherArg,@b@           Object andStillAnother) {@b@    ...@b@}@b@ @b@//缩排8个空格,以避免太深的缩排@b@private static synchronized horkingLongMethodName(int anArg,@b@        Object anotherArg, String yetAnotherArg,@b@        Object andStillAnother) {@b@    ...@b@}

IF语句通常应当以8个空格进行缩排,因为4空格(常规的)会使语句体看起来困难,如: 

//不要使用这种方式@b@if ((condition1 && condition2)@b@    || (condition3 && condition4)@b@    ||!(condition5 && condition6)) { //BAD WRAPS@b@    doSomethingAboutIt();            //MAKE THIS LINE EASY TO MISS@b@} @b@ @b@//应当换成这种方式@b@if ((condition1 && condition2)@b@        || (condition3 && condition4)@b@        ||!(condition5 && condition6)) {@b@    doSomethingAboutIt();@b@} @b@ @b@//或者换成这种方式@b@if ((condition1 && condition2) || (condition3 && condition4)@b@        ||!(condition5 && condition6)) {@b@    doSomethingAboutIt();@b@}

这是三种可以接受的三目条件表达式: 

alpha = (aLongBooleanExpression) ? beta:gamma;  @b@alpha = (aLongBooleanExpression) ? beta:gamma;  @b@alpha = (aLongBooleanExpression) ? beta:gamma;

五、注释

Java程序有两种注释: 实现注释和文档注释. 实现注释在C++中就存在了, 它们以 /*...*/, 和 //. 为分隔符。文档注释为JAVA独有, 并且以 /**...*/.为分隔符。- 文档注释可以被javadoc工具提取出HTML文档。实现注释表示对代码块的注释或者对代码实现细节的注释。文档注释是对代码规格进行描述。

5.1 实现注释的格式 - 程序包含四种风格的实现注释: 块注释, 单行注释, 跟随注释, 和行注释. 

5.1.1 块注释

块注释用于提供文件、方法、数据结构、算法的描述。块注释可以在每个文件开始处或者每个方法之前使用。也可以在其他地方,如方法内使用。方法内部的块注释应当为与代码排列整齐。块注释应当以一个空行开头,以使其与其他代码区分开来,以/*-开始的块注释不会被重新格式化。如: 

/*-@b@ * Here is a block comment with some very special@b@ * formatting that I want indent(1) to ignore.@b@ *@b@ *    one@b@ *        two@b@ *            three@b@ */

5.1.2 单行注释 

短的注释可以用与代码并排的单行注释来实现。如果注释不能在一行中书写,则应当使用多行注释。 单行注释应当以空行开始. 以下是一个单行注释的例子: 

if (condition) {@b@@b@    /* Handle the condition. */@b@    ...@b@}

5.1.3 跟随注释

非常短的注释可以与代码同行,但是应当与代码隔得足够远。如果多个跟随注释与同一个代码块相关, 它们应当排列整齐. 这是一个跟随注释的例子: 

if (a == 2) {@b@    return TRUE;            /* special case */@b@} else {@b@    return isPrime(a);      /* works only for odd a */@b@}

5.1.4 行注释

// 注释分隔符可以注释一个完整的行或者一行的某个部分.它不应当用来对多行代码进行代码注释;无论如何,它可以用来注释掉多行代码。以下是三类型的注释例子: 

if (foo > 1) {@b@ @b@    // Do a double-flip.@b@    ...@b@}@b@else {@b@    return false;          // Explain why here.@b@}@b@//if (bar > 1) {@b@//@b@//    // Do a triple-flip.@b@//    ...@b@//}@b@//else {@b@//    return false;@b@//}

6 – 定义

6.1 每行的数量 

// 推荐每行只定义一个变量,这样便于书写注释。 @b@int level; // indentation level@b@int size;  // size of table@b@//上面的书写方面是首选的。 @b@int level, size;@b@//不要在同一行书写不同类型的定义,如: @b@int foo,  fooarray[]; //错误的!@b@//注意: 上例中,类型和实例间使用了一个空格。另一种可接受的的做法是使用tabs: @b@int	level;	        // indentation level@b@int	size;	         // size of table@b@Object	currentEntry;	 // currently selected table entry

6.2 初始化 - 尽量在定义时对变量进行初始化。其中一个原因是:如果不在定义时初始化,其他变量在初始化时可能会依赖该变量。 

6.3 位置 - 仅仅在块开始的地方放置定义。. (块是指由 "{" 和 "}"围绕的代码.) 不要在变量使用时才定义; 它会使粗心的程序员搞糊涂. 

void myMethod() {@b@    int int1 = 0;         // 在方法块的开头定义@b@ @b@    if (condition) {@b@        int int2 = 0;     // 在"if" 块的开头定义。@b@        ...@b@    }@b@}@b@ // 一个例外的情况是:在JAVA中,FOR循环的索引变量, 可以在FOR语句中定义:@b@for (int i = 0; i < maxLoops; i++) { ... }@b@ // 应当避免局部变量隐藏更高作用域的变量。. 如,不要在块里面定义与外层块中同名的变量:@b@int count;@b@...@b@myMethod() {@b@    if (condition) {@b@        int count = 0;     // 应当避免!@b@        ...@b@    }@b@    ...@b@}

6.4 类和接口语句 - 在编写类和接口时, 应当沿用以下的格式规则: 

1) 在方法名和 "("之间不要有空格。这个"("用于开始参数列表。@b@2) "{"      与定义语句在同一行,并在该行末尾@b@3) }" 单独处于一行,并与定义行左对齐。除非过程体为空,此时"}"应当紧跟在"{"后面,并与"{"处于同一行
class Sample extends Object {@b@    int ivar1;@b@    int ivar2;@b@ @b@    Sample(int i, int j) {@b@        ivar1 = i;@b@        ivar2 = j;@b@    }@b@ @b@    int emptyMethod() {}@b@ @b@    ...@b@}@b@ 方法之间以空行分开。

7 – 语句

1 简单语句@b@每行最多包含一条语句. 如:@b@argv++;       // 正确@b@argc--;       // 正确 @b@argv++; argc--;       // 应当避免!@b@2 复合语句@b@复合语句是指由"{ statements }"包含的语句列表。.@b@“}”应当在块内的语句基础上向左缩排一个层次. @b@“{“应当在复合语句开始行的末尾,(译者注:如在if语句的末尾); “}”应当折行。.@b@“{”,“}”用于包围住块内所有代码,即使块内只有一个单行,也需要用“{”,“}”包围起来。这样可以更容易添加块内语句,避免因为在添加块内语句时忘记加上“{”,“}”而意外的引入BUG@b@3 返回语句@b@有返回值的返回语句不要使用“()”,除非一些显而易见的原因需要加上(). 如:@b@return;@b@ @b@return myDisk.size();@b@ @b@return (size ? size : defaultSize);@b@ @b@4 if, if-else, if else-if else 语句@b@if-else 语句应当如以下格式:@b@if (condition) {@b@    statements;@b@}@b@ @b@if (condition) {@b@    statements;@b@} else {@b@    statements;@b@}@b@ @b@if (condition) {@b@    statements;@b@} else if (condition) {@b@    statements;@b@} else {@b@    statements;@b@}@b@ @b@ 注意: if 语句总是应该使用{}.应当避免以下错误格式:@b@if (condition) //错误,缺少{}!@b@    statement;@b@5 for 语句@b@for应当以以下格式书写:@b@for (initialization; condition; update) {@b@    statements;@b@}@b@ 空的FOR语句(所有工作在FOR语句的初始,条件判断,修改部分完成)应当是以下格式:@b@for (initialization; condition; update);@b@ 在FOR语句中,如果在初始子句、修改子句中使用了“,”操作符, 应当避免使用三个以上的变量. 如果确实有必要,可以在FOR循环前或者循环体结束时使用多条语句.@b@6 while语句@b@while语句应当使用以下格式:@b@while (condition) {@b@    statements;@b@}@b@ 空while语句应当使用以下格式:@b@while (condition);@b@7 do-while 语句@b@do-while语句应当使用以下格式:@b@do {@b@    statements;@b@} while (condition);@b@8 switch语句@b@switch语句应当使用以下格式:@b@switch (condition) {@b@case ABC:@b@    statements;@b@    /* falls through */@b@ @b@case DEF:@b@    statements;@b@    break;@b@ @b@case XYZ:@b@    statements;@b@    break;@b@ @b@default:@b@    statements;@b@    break;@b@}@b@ 没有break语句时,会接着执行下一个case语句块,应当在没有break的case块中加入一个注释.@b@每个switch 应当包含一个default分支. 虽然此时break语句是多余的, 但是当以后增加一个case分支时,它可以防止执行新加的代码(译者注:所以在default分支中加入break是必需的).@b@9 try-catch 语句@b@try-catch语句应当使用以下格式:@b@try {@b@    statements;@b@} catch (ExceptionClass e) {@b@    statements;@b@}@b@ try-catch也可以跟随finally子句.@b@try {@b@    statements;@b@} catch (ExceptionClass e) {@b@    statements;@b@} finally {@b@    statements;@b@}

8 – 空白符

1. 空行@b@通过空行,将逻辑相关的代码分块,可以改善程序的可读性.@b@以下情况,需要用两个空行:@b@一个源文件中的两个段落中。@b@在两个类和接口定义之间@b@以下情况,需要用一个空行:@b@方法之间@b@方法的局部变量和第一条语句之间@b@开始一个代码块或者单行注释时@b@在一个方法内改善可读性时(通过空行使逻辑相关的代码块组织在一起)@b@2 空格@b@在以下情况中,需要使用空格:@b@关键字与其后的“(”之间. 如:@b@       while (true) {@b@           ...@b@       }@b@ @b@ 注意:在方法名和其后的“(”之间不应该有空格。.@b@在参数列表的“,”后面应该有一个空格@b@所有的二元操作符,应当与其操作数据之间有空格,所有一元操作符与其操作数之间不应当有空格符, 如("++"), ("--")。如:@b@    a += c + d;@b@    a = (a + b) / (c * d);@b@    @b@    while (d++ = s++) {@b@        n++;@b@    }@b@    printSize("size is " + foo + "\n");@b@ @b@ For语句的表达式之间. 如:@b@    for (expr1; expr2; expr3)@b@ @b@ 类型转换时,应当在前面加一空格. 如:@b@    myMethod((byte) aNum, (Object) x);@b@    myMethod((int) (cp + 5), ((int) (i + 3)) @b@                                  + 1);

9 – 命名规范 - 命名规范通过使程序易读,从而使用程序更易懂。

标识符类型

命名规则

例子

包名前缀总是以全小写的ASCII 字符书写,并且应当是一个顶级域名。如com, edu, gov, mil, net, org, 或者两个字符的国家代码,参见ISO Standard 3166, 1981.

随后的部分根据组织的国际域名命名. 也可以是公司, 部门, 项目, 机构, 或者登录名.

com.sun.eng

com.apple.quicktime.v2

edu.cmu.cs.bovik.cheese

类名应当是名词, 每个单词首字母大写. 应当保持类名简单,有意义. 使用全名,避免单词缩写(除非缩写是约定成俗并且比全称更普遍。如 URL、HTML).

class Raster;   class ImageSprite;

接口

接口应当象类名那样使用首字母大写.

interface RasterDelegate;   interface Storing;

方法

方法应当是动词, 首个单词的首字母小写, 随后的单词首字母大写.

run();   runFast();   getBackground();

变量

变量的首个单词首字母都小写. 其他单词首字母大写. 变量名不以“-”和“$”开始.

变量名应当短而有意义. 变量也应当好记。. 除非是即用即弃的临时变量,不要使用单字符的变量. 一般的即用即弃临时整形变量可以是 i, j, k, m, 和   n ; 即用即弃字符型临时变量可以c, d, 和 e.

int             i;
char            c;
float           myWidth;

常量

所有类常量和ANSI常量应当全部使用大写字母,单词之间以   ("_")分开. (为调试方便,应当使用ANSI常量.)

static final int MIN_WIDTH = 4;

static final int MAX_WIDTH = 999;

static final int GET_THE_CPU = 1;

10 – 程序惯例

1 访问实例和类变量@b@除非有充分的理由,不要使用公共的类变量、实例变量. 通常,实例变量不需要显式的设置和读取。需要这样做的时候,使用方法调用.@b@一个合适的使用公共实例变量的例子是:当类仅当成数据结构使用,而没有行为(译者注:没有方法调用)。@b@2 类变量和方法@b@避免通过类实例访问类方法和类变量. 应该使用类名代替. 如:@b@classMethod();             //OK@b@AClass.classMethod();      //OK@b@anObject.classMethod();    //避免!@b@3 常量@b@数字常量应该直接在代码中编写, 除非象-1, 0, 和 1这种可以在for循环中作为计数器使用的数字.@b@4 变量赋值@b@避免在同一行中将一个值赋给多个变量. 这使代码阅读更困难,如:@b@fooBar.fChar = barFoo.lchar = 'c'; // 应当避免!@b@ 下面的写法不被接受:@b@if (c++ = d++) {        // 应当避免! (Java 不接受)@b@    ...@b@}@b@ 应当这样写@b@if ((c++ = d++) != 0) {@b@    ...@b@}@b@ 不要为了提高性能而使用内嵌的赋值语句. 那是编译器的任务. 如:@b@d = (a = b + c) + r;        // 应当避免!@b@ 应当这样写@b@a = b + c;@b@d = a + r;@b@5 其他惯例@b@5.1 括号@b@使用括号来改变表达式中的运算次序是不错的主意. 有时也可以强制加上()以使代码更好理解,尽管在某些情况下不加()的结果正确的.@b@if (a == b && c == d)     // 应当避免!@b@if ((a == b) && (c == d)) // 正确@b@5.2 返回值@b@如:@b@if (booleanExpression) {@b@    return true;@b@} else {@b@    return false;@b@}@b@ 应当被写成@b@return booleanExpression;@b@ 同样的,@b@if (condition) {@b@    return x;@b@}@b@return y;@b@ 应当被写成@b@return (condition ? x : y);@b@5.3 ?前的条件表达式@b@如果条件表示式包含二元操作符,应当用()包围起来. 如:@b@(x >= 0) ? x : -x;@b@5.4 特殊注释@b@在注释中使用XXX表示假的,但是可能会存在的事物. 用 FIXME 假的并且被确定不存在的事物.

11 – 代码示例

11.1 JAVA代码示例 - 以下是一个完事的java源文件例子:

/*@b@ * @(#)Blah.java        1.82 99/03/18@b@ *@b@ * Copyright (c) 1994-1999 Sun Microsystems, Inc.@b@ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.@b@ * All rights reserved.@b@ *@b@ * This software is the confidential and proprietary information of Sun@b@ * Microsystems, Inc. ("Confidential Information").  You shall not@b@ * disclose such Confidential Information and shall use it only in@b@ * accordance with the terms of the license agreement you entered into@b@ * with Sun.@b@ */@b@ @b@ @b@package java.blah;@b@ @b@import java.blah.blahdy.BlahBlah;@b@ @b@/**@b@ * Class description goes here.@b@ *@b@ * @version         1.82 18 Mar 1999@b@ * @author  Firstname Lastname@b@ */@b@public class Blah extends SomeClass {@b@    /* A class implementation comment can go here. */@b@ @b@    /** classVar1 documentation comment */@b@    public static int classVar1;@b@ @b@    /** @b@     * classVar2 documentation comment that happens to be@b@     * more than one line long@b@     */@b@    private static Object classVar2;@b@ @b@    /** instanceVar1 documentation comment */@b@    public Object instanceVar1;@b@ @b@    /** instanceVar2 documentation comment */@b@    protected int instanceVar2;@b@ @b@    /** instanceVar3 documentation comment */@b@    private Object[] instanceVar3;@b@ @b@    /** @b@     * ...constructor Blah documentation comment...@b@     */@b@    public Blah() {@b@        // ...implementation goes here...@b@    }@b@ @b@    /**@b@     * ...method doSomething documentation comment...@b@     */@b@    public void doSomething() {@b@        // ...implementation goes here... @b@    }@b@ @b@    /**@b@     * ...method doSomethingElse documentation comment...@b@     * @param someParam description@b@     */@b@    public void doSomethingElse(Object someParam) {@b@        // ...implementation goes here... @b@    }@b@}