JAVA代码编程规范

  1. 概述
    1. 编程规范的必要性

        代码编程规范之所以重要是因为:

  1. 软件生命周期中的80%时间是软件维护期;
  2. 几乎没有任何软件在其整个生命周期中一直由它的原作者来负责维护;
  3. 代码编程规范能够增加软件的可读性,使得软件工程师更快更准确地理解新代码
  4. 编程规范能提高软件的封装性;
    1. 规范文档的一些要求

后面文中将深入讨论结构良好的程序文档的规则和要求。一个结构良好的文档应首先做到以下几点。

  1. 文档注释应能增加代码的可读性

编写注释的目的是使你、你的开发伙伴以及后续的开发人员更好地理解你的代码。SUN公司JAVA开发组的Nagle曾说过“如果程序不值得写文档的话,意味着代码也不值得运行”。

 

  1. 避免文档的过度修饰

六七十年代的COBOL语言开发着有一种注释习惯,通常用星号画一个方盒子来填写注释。这样做的确很好看,但对于最终产品来讲没有太多的益处。应当注意文档中注释和代码的比例,代码的注释应当简洁、明了。

 

  1. 在编码前就开始写文档

原则上讲,我们看一段代码总能发现它在做什么。例如,下面这段代码中,我们能分析出代码的行为,但不能真正看出它的确切语义。

        if ( grandTotal >= 1000.00)

        {

        grandTotal = grandTotal*0.95;

        }

在注释文档中应说明代码所表达的语义和编码设计思想,而不应只是就事论事的讲述代码的行为。

    1. 如何使代码简洁
  1. 为代码写注释文档
  2. 将代码从逻辑上分段
  3. 合理的使用空行
  4. 遵守“30秒规则”,提高代码的可读性
  5. 书写较短的代码行
  1. 文件组织

一个JAVA源文件是由用空白行和注释分隔开的很多部分组成的,通常文件长度应该小于2000行。

每一个Java源文件都包括一个公共的类或接口。当私有类或接口与公共类相关联的时候,通常可以将其与公共类放在同一个源文件当中。公共类应是文件中的第一个类或接口。

Java源文件的组织结构如下:

  1. 文件开始的注释段
  2. Package和Import的声明
  3. 类和接口声明
    1. 文档开头的注释

所有源文件的开始部分都要有一个C语言风格的注释段,列出本程序的类名、版本信息、日期、版权声明。如下所示。

/*

 *  Classname

 *

 *  Version information

 *

 *  Date

 *

 *  Copyright notice

 */

    1. Package和Import声明

通常Java源文件中第一个非注释行是一个Package声明,然后是Import声明。如下所示。

package java.awt;

import java.awt.peer.CanvasPeer;

 

    1. 类和接口声明

下表描述了类和接口声明中的一些部分,按照其出现顺序列出:

 

类和接口说明

说明

Class/Interface 文档型注释

/**

 *

 */

Class或Interface声明

 

Class或Interface的实现声明

该段注释中应该包括任何与类和接口有关的,但又不适于放在文档注释区中的注释说明

类静态变量

变量出现的顺序为,首先公共变量,然后protected变量,然后是包package一级的变量,然后是私有变量

变量实例

首先是公共变量,然后protected变量,然后是包package一级的变量,然后是私有变量

构造函数(Constructors)

 

方法

方法应该按照功能而不是范围和可访问性来分类。例如,一个私有的类方法可以在两个公共的Instance方法的中间。这样做的目的是提高代码的可读性。

    1. 文档的缩进规则

文档中的缩进基本单位是4个空格。Tab键应当设置为4个空格键。

      1. 行的长度

代码行的长度应小于80个字符,否则不能被编辑和处理工具很好的处理。通常文档中代码例子的长度不超过70个字符。

      1. 代码行的分割

当一个表达式因太长等原因不适于单行放置的时候,可以根据下面的规则来进行分割:

  1. 在逗号后面分割;
  2. 在操作符前分割;
  3. 应选择高一级的分割而不是低一级的分割;
  4. 将换行后的表达式的开始部分与前一行的同一级表达式对齐;
  5. 如果上述规则使得代码难读或代码集中在行的右侧,应4空格的缩进规则;

 

下面是一些方法调用行分割的例子

   someMethod(longExpression1, longExpression2, longExpression3,

      longExpression4, longExpression5);

   Type var =

      someMethod1(longExpression1,

      someMethod2(longExpression2,longExpression3))

以上是好的格式,以下就不是很好:

   Type var = someMethod1(longExpression1

      someMethod2(longExpression2, longExpression3))

 

下面是两个算术表达式的换行分割的例子。

   LongName1 =

longName2*( longName3 + longName4 – longName5)

            + 4 * longName6; // 较好的分割方式

 

LongName1 =

longName2*( longName3 + longName4

– longName5)   + 4 * longName6; // 尽量避免这种分割方式

  

其中,第一方式的较好,因为换行分割点位于括号的外边,同第二种分割相比是分割的级别较高。

 

当方法中参数很多时,提倡如下的书写:

   public void someMethod(Type longExpression1,

Type longExpression2,

Type longExpression3,

Type longExpression4,

Type longExpression5){

         ...

   }

 

同样,当IF语句或其他循环语句较长时,提倡如下的书写:

       if ((condition1 && condition2 )

   || (condition3 && condition4)

      || !(condition5 && condition6)) {

      doSomethingAboutIt();

   }

 

下面是3个可接受的表达式的书写方式:

   alpha = (alongBooleanExpression) ? beta : gamma;

   alpha = (alongBooleanExpression) ? beta

: gamma;

   alpha = (alongBooleanExpression)

            ? beta

            : gamma;

    1. 空行和空格的使用
      1. 空行的使用

用空行将代码段按照逻辑进行分割有助于提高文件的可读性。空2行的方法应在如下情况中采用:

  1. 在一个源文件中的各个代码段之间用;
  2. 在类定义和接口定义之间使用。

 

空1行的分割方法应该在下列情况中采用:

  1. 在各个方法之间;
  2. 在一个方法中的局部变量和它的首次声明之间;
  3. 在块注释和单行注释之前
  4. 在一个方法中用空行将代码段从逻辑上划分,以提高文档的可读性
      1. 空格的使用

空格应该在下列情况下使用:

  1. 一个系统保留字和他后面的括号应该用空格分割。例如,

   while (true) {

      ...

   }

这样做有助于把系统保留字和方法调用区分开来,因为方法调用与其后的调用参数括号()之间是没有空格的。

  1. 在逗号后面用于分隔的多个参数;
  2. 除了“.”外的所有二元运算符都应用空格与其相应的操作数隔开。空格不能用在一元操作符,如一元加++或一元减-- ,与其相应的操作数之间。例如,

   a += c + d;

   a = (a + b) / (c * d);

   while (d++ = s++) {

       n++;

   } 

   prints(“size is ” + foo + “\n”);

  1. for 循环表达式应该用空格分开。例如,

   for (expr1; expr2; expr3);

  1. 强制类型转换(cast)后面应该添加空格。例如,

   myMethod((byte) aNum, (Object) x);

   myMethod((int) (cp + 5), ((int) (i + 3))

   + 1);

 

  1. 注释规则

JAVA有三种注释方式。如下表所示。

注释方式

使用场合

例 

文档型(Document)注  释

 

这种注释放在程序代码中的,接口函数、类、成员函数和域的声明定义之前。

文档型注释由javadoc来处理。如右图所示,为一个类创建一个外部说明文档。

/**

   Customer- A customer is any

   person or organization that

   we sell services and products

   to.

   @author S.W. Ambler

*/

 

C 风格的注释

一般来说,用C风格的注释来说明一段代码是不合适的。

    这种方式主要用在维护和修改代码时,或者调试中临时关闭一段代码时使用。

 

/*

  This code was commented out

  By J.T.Kirk on Dec 9,1997 because it was replaced by the prededing code. Delete it after two years if it is still not applicable.

 

  … … (the source code)

*/

 

单行注释

一般在成员函数的内部采用单行注释,主要用来说明事务逻辑(business logic)、代码段、临时变量的声明定义。

//Apply a 5% discount to all invoices

//over $1000 as defined by the Sarek

// generosity compaign started in

// Feb. Of 1995

 

    1. 基本原则
  1. 注释应能使代码更加明确
  2. 避免注释部分的过度修饰
  3. 保持注释部分简单、明确
  4. 在编码以前就应开始写注释
  5. 注释应说明设计思路而不是描述代码的行为
    1. 注释的内容

下表说明了各个部分注释的主要内容要求:

注释项

注释的内容

Arguments/parameters

  1. 参数的类型
  2. 如何使用
  1. 以及使用的限制
  2. 例子

Fields/properties

  1. 可以描述使用的例子;
  1. 一致性问题,
  2. 例子

classes

  1. 说明类的用途
  2. 已经知道的bug
  1. 该类开发和维护的历史记录

Compilation unite

  1. 每一个class/interface的定义包括一些简单的描述,
  1. 名字或定义信息
  1. 版权信息

Interfaces

  1. 接口的用途
  2. 如何使用该接口

局部变量local variables

  1. 变量的用途和目的

成员函数的文件注释

documentation comments

  1. 成员函数的用途和设计目的
  2. 成员函数的参数说明
  3. 成员函数返回说明
  4. 已知道的bug
  5. 成员函数抛出的任何异常
  6. 访问控制设计
  7. 代码改变得历史记录
  8. 成员函数调用的例子
  9. 应用的前提条件

成员函数的内部注释

internal comments

  1. 结构控制说明
  2. 代码设计目的
  3. 局部变量
  4. 复杂代码的解释
  5. 处理顺序

包packages

  1. 包的基本原理
  2. 包中的类(class)

 

    1. 注释的运用

JAVA程序有两类注释:一类是实现性注释(implementation comments),另一类是文档型注释(documentation comments)。其中,Implementation 注释有C和C++两种格式,/*...*/ 和//。文档型注释是JAVA程序所独有的,在/**...*/中限定。文档型注释能够被javadoc文件工具提取到HTML文件中。

Implementation注释用于注释代码或者注释特殊的实现。文档型注释主要是描述代码段的说明,从一种非面向实现的角度来写给开发人员阅读读,这些开发人员可能手边并没有源代码。

通常注释应该是给代码一个总的描述或者提供从代码本身不太容易看出的附加性信息。注释的内容应只与读代码和理解代码有关。例如,关于相应的包(package)是如何构建,以及存放在什么目录中,不应该包括在注释中。对代码中不太明显的设计意图进行说明是应该的,但也应避免对一些明显的信息进行重复说明,尽量避免那些随着代码的维护会过时的注释。

    注意:

  1. 过于频繁的注释常常意味着代码质量较低。但你觉得必须频繁添加注释时,应考虑重写该段代码了。
  2. 注释内容不应封在星号(*)或者其它字母围成的矩形框中;注释中不应带有特殊注释字符如制表符(form-feed)和退格符(backspace)。
    1. Implementation注释的格式

JAVA程序段中可以有4种形式的实现注释:块注释(block)、单行注释、后注释(trailing)、行尾注释(end-of-line)。

      1. 块注释

块注释用来提供文件、方法、数据结构和算法的描述。块注释主要用在每个文件和方法的开头部分,有时也可用在方法的中间。在一个函数和方法中的块注释应该遵照缩进规则排列到说明对象的同一级深度。

通常块注释前用一个空行和其它的代码段分开。

/*

 * Here is a block comment.

 */

 

另外,用/* - 开始的块注释能够被indent(1)识别出,作为块注释的开始。例如,

/*-

 * Here is a block comment with some very special

 * formatting that I want indent(1) to ignore.

 *

 */

注意: 如果你自己不用indent(1),你没有必要用/* -注释开始。

      1. 单行注释

单行注释应与其注释的代码处在同一缩进级别中。如果一个注释能写成单行,那么没有必要写成块注释。单行注释前面应有一个空格。例如:

    if (condition) {

       /* Handle the condition. */

       ...

   }

 

      1. 后注释(trailing)

    一些非常短的注释可以加在代码的同一行内,但是应该把注释和代码分开足够大的间隔,以增加可读性。如果在一个小代码段中有多个后注释,那么应将其用TAB缩进对齐。

    If (a == 2) {

       Return TRUE;           /* special case */

   } else {

       return isPrime(a);     /*work only for odd a */

   }

注:不提倡使用

      1. 行尾注释(End-of-line)

“//”注释符能够将整行或部分行注释掉,它不能用在连续的多行文本注释中。它可以用在将小段连续的代码注释掉。所有的3种风格如下所示:

   If (foo > 1){

        // Do a double-flip

       ...

   }

   else{

      return false;    //Explain why here(不提倡使用)

   }

 

   // if (bar > 1) {

   //

   //    // Do a triple-flip.

   //     ...

   //}

   //else{

   //     return false;

   //}

    1. 文档型注释(Documentation)

JAVA SDK本身提供了较强的代码文档生成功能,只要代码中的注释符合一定的规则就可利用javadoc工具自动生成代码文档。Javadoc 是一种工具,它用于对一组源文件中的声明和文档注释进行语法分析,并生成一组 HTML(HyperText Markup Language,超文本标记语言)页,描述类、内部类、接口、构造函数、方法和域。文档型注释与javadoc紧密相关,可通过灵活运用文档型注释让javadoc自动生成丰富详实的代码文档。Javadoc可从*.java源文件、包说明文件、概述说明文件,以及其它文件中提取信息生成文档。

文档型注释(documentation)主要描述JAVA类、接口、构造器、方法和域。每一个文件注释的内容在/**...*/, 一个类和接口一个注释段。注释应该紧接着类声明的前面。文档型注释的格式是/**及其之后的空格都被javadoc忽略,后续行中的第一个*也被忽略。

/**

 * The Example class provides ...

 */

public class Example { ...

注意:

最上一级的类和接口是不缩进的,第一行是(/**)。

其它的成员函数和构造模板要用4空格的缩进。

如果需要对类、接口进行注释但是又不适于采用文档型注释,可以用块注释或者单行注释。例如,一个类的详细实现信息可以通过在类声明后的块注释来做。文档性注释不能放在一个方法和构造之内。

      1. 位置

源代码的文档型注释放在任何实体(类、接口、方法、属性、构造函数)的开头。

注意

  1. 只有紧挨着类、接口、方法、属性、构造函数声明的那块注释才被生成javadoc文档,每个声明语句前只有一块注释可被javadoc识别。
  2. 函数内部的注释不会生成javadoc文档。

例如下面例子中的注释因为放在了import语句之前,而无法被生成文档:

/**   

* This is the class comment for the class Whatever.   

*/   

import com.sun;   // MISTAKE - Important not to put import statement here   

public class Whatever {   

}

 

注释的第一句话

每块文档型注释的第一句话应该是一个概括型语句,可简洁但完整地描述本块注释将要表达的意思。Javadoc将使用该句文字作为成员方法的概述。

注释内部的HTML标签

文档型注释遵循HTML语法规则,可以在注释中插入任何想要的HTML标签以对注释进行格式化。从注释生成的文档中缺省是没有换行的,如需要在最终文档中体现换行,需要在注释中增加换行标签:

/**

 * 查询指定条件上的线路配置集。

 * 该方法是静态方法,无需实例化一个本类的对象即可调用本方法。

 * @param neName 网元的名字

 * @param cpn 表明需要查询哪个机框、板、端口上的信息。注意本方法不按机架

 * 进行查询,因为一个机架上会有两个网元,所以CPN中的rack设为-1。按从细到粗的

 * 顺序,CPN中的其它字段也可设置为-1,表示查询仅精确到上一级单位。

 * @return 返回AdslLineConfProfileTable对象组成的Vector

 **/

如需加粗某些文字:

/**

 * This is a doc comment.

 * @see java.lang.Object

 */

 

javadoc自身的标签

javadoc提供了若干种自定义标签,充分运用这些标签可使生成的文档结构更合理,实用性更强。Javadoc标签以@开头,且是大小写敏感的。包括以下几种标签:@author 、{@docRoot}、@deprecated、@exception、{@link}、@param、@return、@see、@serial、@serialData、@serialField、@since、@throws、@version。下面简要介绍几种很常用且比较重要的标签。

@author  name-text

将代码作者的名字生成到文档中。

@param  parameter-name description

描述方法的参数

@return  description

描述返回值

@see  reference

增加一个See Also的链接。

      1. javadoc标签的使用

位置

标签

概述文档,一般是overview.html

@see、{@link}、@since

包文档

@see、{@link}、@since、@deprecated

类和接口文档

@see、{@link}、@since、@deprecated、@author、@version

属性文档

@see、{@link}、@since、@deprecated、@serial、@serialField

构造函数或方法文档

@see、{@link}、@since、@deprecated、@param、@return、@throws (@exception)、@serialData

尽量不要使用括号中的标签,如:@exception;因为在JDK1.2中已经用括号前面的替代了。

      1. 加入样例代码

对于较复杂的类或方法,最好在其注释文档中增加一段如何使用本类(方法)的例子代码。由于javadoc生成的文档会忽略空格和换行,应在样例代码段前后加上

标签:

/**

 * A class representing a window on the screen.

 * For example:

 *

 *    Window win = new Window(parent);

 *    win.show();

 *

 *

 * @author  Sami Shaio

 * @version %I%, %G%

 * @see     java.awt.BaseWindow

 * @see     java.awt.Button

 */

class Window extends BaseWindow {

   ...

}

      1. 生成javadoc文档

下面给出一个简单的批处理文件用于生成javadoc文档:

del filelist.txt

dir /b /s ..\ems5100\src\*.java > filelist.txt

dir /b /s ..\emsbase\src\*.java >> filelist.txt

javadoc -windowtitle IPMS源程序文档(JavaDOC) -private @filelist.txt

 

另外,Javadoc 有许多有用的选项,有些相对其他更为常用。下面是实际中我们用来在 Java 平台 API 上运行 javadoc 的命令,它使用了 makefile 变量(除了未列出所有要建文档的包之外)。

javadoc -sourcepath /jdk/src/share/classes /* 源文件路径        */

        -d /jdk/build/api                        /* 目的目录          */

        -use                                         /* 添加“用法”文件  */

        -splitIndex                                  /* 分割索引 A-Z      */

        -windowtitle $(WINDOWTITLE)              /* 添加窗口标题      */

        -doctitle $(DOCTITLE)                    /* 添加文档标题      */

        -header $(HEADER)                        /* 添加运行页眉文本  */

        -bottom $(BOTTOM)                        /* 添加底部文本      */

        -group $(GROUPCORE)                      /* 概述页的核心标题  */

        -group $(GROUPEXT)                       /* 概述页的扩展标题  */

        -overview overview-core.html             /* 概述文本          */

        -J-Xmx180m                                   /* 180MB 内存       */

        java.lang java.lang.reflect              /* 要建立其文档的包  */

        java.util java.io java.net        

        java.applet

 

WINDOWTITLE = 'Java 平台 1.2 最终 API 规范'

DOCTITLE = 'JavaTM Platform 1.2          Final API Specification'

HEADER = 'Java Platform 1.2
Final'

BOTTOM = '

       提交 bug 或功能

Java Sun Microsystems , Inc 在美国和其他国家的商标或注册商标。
Copyright 1993-1998  Sun Microsystems, Inc. 901 San Antonio Road,
Palo Alto, California, 94303, U.S.A.
保留所有权利。
'

GROUPCORE = '"核心包" "java.*:com.sun.java.*:org.omg.*"

GROUPEXT  = '"扩展包" "javax.*"'

 

如果省略 -windowtitle 选项,则 javadoc 将文档标题复制到窗口标题。-windowtitle 选项是没有必要的,除非文档标题包含 HTML 标记。

  1. 变量的声明
    1. 每行变量声明个数

   通常JAVA代码中一行只声明一个变量:

   int level;       // indentation level

   int size;    // size of table

对比:

   int level, size;

    1. 变量初始化

应在一个变量声明的时就对它进行初始化工作。

    1. 变量声明的位置

变量声明只应该放在代码段的开始部分。代码段是指花括号{}所包括的区域。严禁到使用时才声明变量。

   void myMethod(){

       int int1 = 0;    //beginning of method block

 

      if (condition) {

          int int2 = 0; // beginning of “if” block

         ...

      }

   }

唯一的例外是for循环中的循环变量,如

   for (int i = 0; i < maxLoops; i++){ ... }

 

   为了避免局部变量被高一级的变量所覆盖,应避免在局部代码块中采用同样的变量名称。例如,

   int count;

   ...

   myMethod() {

       if (condition) {

          int count;          // 应避免这种情况

          ...

       }

       ...

   }

    1. 类和接口的声明

当编写JAVA的类和接口是应该遵循下列格式规则:

  1. 在方法名称和其后的括号()之间没有空格;
  2. 声明类和接口时,表示代码块开始的花括号”{“处在声明的同一行的末尾;
  3. 花括号”}“应该与相应的花括号”{“所在的行缩进对齐;
  4. 方法与方法之间用空行隔开。

class Sample extends Object {

   int ivar1;

   int ivar2;

 

   Sample(int i, int j) {

       ivar1 = i;

       ivar2 = j;

}

// 空行

int emptyMethod()

};

  1. 语句
    1. 简单语句

每一行应该只包括一个语句,例如:

        argv++;                   //正确

        argc++;                    //正确

        argv++; argc--;                //错误

    1. 复合语句

复合语句是指用一对花括号包围起来的任意数量的简单语句{语句}。

  1. 括起来的语句应该比复合语句缩进至少一层;
  2. 开始括号应该在复合语句末尾;结束括号应该在新的一行并且和复合语句括号的开始行对齐;
  3. 当它们作为控制流程的一部分的时候,应该用括号把所有的复合语句括起来,即使只有一句简单语句,比如if-else或者for语句。这样可以更方便的加入语句而不会引起由于忘掉加括号而引起的偶然性的错误。
    1. 返回语句

带值的返回语句不需要用圆括号,除非有时不得不用括号使返回结构更加明显。例如:

   return;

   return myDisk.size( );

   return (size ? size : defaultSize);

    1. if,if-else,if else-if else语句

if-else类语句有如下几种形式:

   if (condition) {

       statements;

   }

 

   if (condition) {

       statements;

   } else {

       statements;

   }

 

   if (condition) {

       statements;

   } else if (condition) {

       statements;

   } else {

       statements;

   }

 

        注意:if语句一定要用花括号{};要避免以下混淆形式:

        if (condition)      //要避免这种对花括号的忽略!

       statement;  

    1. for语句

for语句形式如下:

   for (initialization; condition; update) {

       statements;

   }

        一个空的for循环语句的形式如下:

   for (initianlization; condition; update);

当for循环的initianlization部分和update部分中有多个用逗号隔开的变量时,通常变量的数量不应该超过3个。如果必要的话,可以在for循环的之前(initianlization部分前)或者在循环的尾部(update部分)使用单独的语句来说明。

    1. while 循环语句

        一个while语句结构如下:

while (condition) {

      tatements;

   }

下面是一个空的while循环语句:

   while (condition);

    1. do-while 语句

        一个do-while 循环语句的形式如下:

   do {

      statements;

} while (condition);

 

    1. switch语句

        一个switch语句的结构如下:

   switch (conditon) {

       case ABC:

          statements;

          /* falls through */

       case DEF:

          statements;

         break;

       case XYZ:

          statements;

          break;

       default:

          statements;

          break;

   }

每一个switch语句中应该包括一个default case语句。

    1. try-catch 语句

        try-catch语句有以下格式:

   try {

       statements;

   } catch (ExceptionClass e) {

       statements;

   }

 

        try-catch语句也可以跟随finally,它总是被执行,而不受异常是否抛出的影响。   

   try {

       statements;

   } catch (ExceptionClass e) {

       statements;

   } finally {

       statements;

   }

 

  1. 命名规范

   命名规范的目的是提高程序的可读性,使程序易于理解。

    1. 命名的基本原则

基本命名原则:

  1. 使用完整的英文描述符准确描述变量variable/域field/类class

较好的命名应该象firstName、grandTotal、CorporateCustomer, 而诸如x1、y1等命名反映任何命名含义,而且造成代码难以理解、维护和改进。

  1. 采用应用领域相关的术语来命名

如果软件开发人员应注意软件用户的一些约定术语,不应当随意的创造术语。这会降低软件的易用性。

  1. 采用大小写混合的方式提高命名的可读性

一般情况下应该用小写字母来命名,其中类(class)和接口(interface)名称的首字母用大写。

  1. 谨慎使用缩写

设计命名中应该慎用缩写命名。如要采用,则应采用统一的缩略规则,并且在文中的相应部分统一采用缩写。例如,采用num作为number的缩写,那么在整个文档中应该始终使用该缩写。

  1. 避免太长的命名

命名的长度应小于15个字母(但是可以使用更长的形式,以便更好的表达意思)。

  1. 避免采用仅有大小写不同命名

命名时应避免采用几乎相同的名称。例如,变量名称persistentObject和persistentObjects不应当同时运用;anSqlDatabase和anSQLDatabase也不应同时使用。

  1. 将标准缩略词的首字母进行大小写变化

有时名称中会含有固定的缩略词,例如SQL代表Standard Query Language. 而在命名时sqlDatabase和SqlDatabase就比sQLDatabase和SQLDatabase易于阅读。

    1. 成员函数的命名规则

成员函数名称应采用完整的英文单词组成,除第一个单词外其余的成员单词的首字母用大写。成员函数取名采用动宾结构,名称中的第一个词为动词。例如,

openAccount();

printMailingLabel();

save();

delete();

成员函数的命名应能够准确、简洁地表示其功能。虽然函数名稍微有点长,但还是值得的,因为它能够增加代码的可读性。

      1. 成员访问函数的命名

对(fields/property)赋值的访问性函数,通常的命名方式是用get/set+“访问对象名”。当对象为布尔型时,用is+“访问对象名”构成,其中对象名称用大小写混合的方式,首字母大写。这些命名约定是JDK标准和JAVA Beans开发时所要求的。

get型函数

        Get型函数返回一个域(field)的值。在命名时将“get”作为第一个单词;如果是boolean型的域,那么将“is”作为函数名称的第一个单词。如:

   getFirstName();

   getAccountNumber();

   getLostEh();

   isPersistent();

   isAtEnd();

 

set型函数

这些函数主要用来对一个域(field)来赋值,命名时将“set”作为第一个单词。如:

        setFirstName(string aName);

   setAccountNumber(int anAccountNumber);

  setReasonableGoals(Vector newGoals);

   setAtEnd(boolean isAtEnd);

 

 

 

构造函数Constructor

构造函数是成员函数的一种,当一个对象初次创建的时候负责对象初始化工作。构造函数的名称总是与其创建的类完全相同。如:

   Customer();

   SavingAccount();

   PresistenceBroker();

    1. 属性域(fields/property)的命名

通常应该用完整的英文单词来命名一个域,使其名称能够很好的反映其代表的值。如:

   firstName;

   zipCode;

   unitPrice;

   discountRate;

   orderItems;

    1. 组件的命名

组件接口的命名应该采用全英文单词,后缀为该组件的类型,如botton、list等。命名应能够较好表达该组件的用途,并使得该组件易于在applet或application中查找。组件应避免取诸如botton1、botton2等抽象的名称。如:

okButton;

customerList;

fileMenu;

newFileMenuItem;

    1. 常量的命名

常量的命名常用全英文单词来说明,所有的字母采用大写方式,单词之间用下划线连接。

如:

MINMUM_BALANCE;

MAX_VALUE;

DEFAULT_START_DATE;

    1. 数组的命名

数组(array)和vector的命名方法是,用array和vector所存对象名称的复数表示,名称为全英文单词组成,非开头单词的首字母采用大写。例如,

customers;

orderItems;

aliases;

 

    1. 局部变量的命名标准

局部变量的命名规范与前面提到的field命名原则类似,命名用全英文单词,其中非开头单词的首字母大写。

      1. 流(Streams)的命名

当在一个成员函数中打开一个输入输出流的时候,SUN公司的命名约定如下:

  1. 输入流

命名用in +“流名称”;

  1. 输出流

命名用out +“流名称”;

  1. 输入/输出流

命名用inOut +“流名称”;

 

      1. 循环变量的命名

循环变量的命名一般用i、j、k来表示,也可以用更有意义的单词来表示。对于嵌套循环,一般外层循环用i, 第二层用j, 依此类推。

 

      1. 异常(Exception)处理中的命名

异常处理在JAVA代码编程中是十分常用的。通常用小写ex 来作异常对象(exception objection)的对象。例如,

   public LocaLize(String FileName) {

      try {

         filename = FileName;

         jbInit();

      }

      catch(Exception ex) {

         ex.printStackTrace();

      }

   }

      1. 通用对象命名约定

下表是SUN公司的一些通用变量和对象的JAVA命名约定。

变量类型

命名前缀

offset

Off

length

Len

byte

B

char

C

double

D

float

F

long

L

Object

O

String

S

Arbitrary value

V

    1. 类、接口、包的命名

下表总结了类、接口、包的命名规则。

定义类型

命名规则

例子

Packages

包名称的前缀总是用小写的ASCII字母来表示的,并且总是采用一级域名,如com,edu,gov,mil.net,ort,或者是ISO 3166标准中规定的国家名的2字母缩写。

一个包名称后面的组件名根据一个组织的各个名称约定来取。

 

com.sun.eng

com.apple.quicktime.v2

edu.cmu.cs.bovik.cheese

com.zte.resmaster.util

Class

类名称应该是名词,且其内部的每一个词的首字母应大写。类名应简单而有意义。组成类名的单词不应用缩写。除非这些缩写已被广泛理解,如URL和HTML。

类名尽量使用名词,或者名词+动词的形式。

Class Raster;

Class ImageSprite;

Inerfaces

接口名称的大写规则与类名相同。

接口名尽量使用形容词,如:Runnable。或者名词,并且名词最好是带er,如:RequestHandler。

Interface RasterDelegate     interface Sroring

Methods

方法的取名应该是动词。它是大小写混合的。成员单词的首字母小写,且中间单词的首字母大写

Run();

RunFast();

GetBackground(

Variables

除了变量外,所有的instance,calss,和类常量是大小写混合的。成员单词的首字母小写,且中间单词的首字母大写。另外,变量名称不应该用下划线“_”和“$”符号开始。

 

变量名称应该简短但有意义。除非是临时使用的变量外,不应当用单个单词来命名变量。

 

通常临时变量命名时,i,j, k,m,n,来表示整型变量;c,d,e表示字符型变量

 

Int  i;

Char c;

Float myWidth;

Constants

所有的常量名称应该用大写字母表示,各个成员单词之间用下划线“_”相连接。

 

Static final int MIN_WIDTH = 4;

 

Static final int MAX_WIDTH = 999

Static final int GET_THE_CPU = 1;

    1. J2EE命名规范

在开发J2EE系统的过程中,随着系统开发的深入,如何控制各种对象和资源的命名就成为一个使系统成功的一个重要因素。任何随意性都将导致系统在后期产生混乱,结构不清晰,导致更多的维护成本。

      1. EJB包结构

实体Bean

Bean   :com.company.projectname.subsystem.ejbname.ejb.EjbnameEJB

Remote :com.company.projectname.subsystem.ejbname.ejb.EjbnameRemote

Home   :com.company.projectname.subsystem.ejbname.ejb.EjbnameHome

例如:用户对象

    Bean   : com.zte.resmaster.sysmanage.user.ejb.UserEJB

    Remote : com.zte.resmaster.sysmanage.user.ejb.UserRemote

Home   : com.zte.resmaster.sysmanage.user.ejb.UserHome

 

会话Bean

Bean   : com.company.project.subsystem.ejbname.manager.EjbnameEJB

Remote : com.company.project.subsystem.ejbname.manager.EjbnameRemote

Home   : com.company.project.subsystem.ejbname.manager.EjbnameHome

例如:用户对象

    Bean   : com.zte.resmaster.sysmanage.user.manager.UserEJB

    Remote : com.zte.resmaster.sysmanage.user.manager.UserRemote

Home   : com.zte.resmaster.sysmanage.user.manager.UserHome

 

数据值对象(Data Value设计模式中采用)

com.company.projectname.subsystem.ejbname.model.EjbnameModel

例如:用户对象

        com.zte.resmaster.sysmanage.user.model.UserModel

 

DAO对象

DAO接口:com.company.projectname.subsystem.ejbname.dao.EjbnameDAO

DAO实现:com.company.projectname.subsystem.ejbname.dao.EjbnameDAOImpl

DAO数据库实现:

com.company.projectname.subsystem.ejbname.dao.EjbnameDAODatabase

DAO工厂:com.company.projectname.subsystem.ejbname.dao.EjbnameDAOFactory

例如:用户对象

    DAO接口:com.zte.resmaster.sysmanage.user.dao.UserDAO

DAO实现:com.zte.resmaster.sysmanage.user.dao.UserDAOImpl

DAOOracle实现:com.zte.resmaster.sysmanage.user.dao.UserDAOOracle

DAOSybase实现:com.zte.resmaster.sysmanage.user.dao.UserDAOSybase

DAO工厂:com.zte.resmaster.sysmanage.user.dao.UserDAOFactory

 

异常

com.company.projectname.subsystem.ejbname.exceptions.XXXException

例如:用户关键字已经存在的异常

com.zte.resmaster.sysmanage.user.exceptions.UserDupKeyException

 

工具类

com.company.projectname.subsystem.ejbname.util.Xxxx

例如:

com.zte.resmaster.sysmanage.user.util.UserEJBHelper

      1. Servlet包结构

Servlet

com.company.projectname.subsystem.web.XxxServlet

例如:数据网子系统

    com.zte.resmaster.datanet.web.MainServlet

 

Handler处理类

com.company.projectname.subsystem.web.handlers.ObjectHandler

例如:线路对象

    com.zte.resmaster.datanet.web.handlers.LineHandler

 

Web工具类

com.company.projectname.subsystem.util.XXX

例如:

com.zte.resmaster.datanet.util.DataUtil

 

Web异常类

com.company.projectname.subsystem.exceptions.XXXException

例如:通用错误类

com.zte.resmaster.datanet.exceptions.GeneralFailureException

      1. 通用工具包结构

数据

com.company.projectname.util.data.XXX

例如:

com.zte.resmaster.util.data.SystemProperties

 

跟踪调试

com.company.projectname.util.tracer.XXX

例如:

com.zte.resmaster.util.trace.Debug

 

UI(用户界面)

com.company.projectname.util.ui.XXX

例如:字体选择面板

        com.zte.resmaster.util.ui.FontChooserPanel

 

Theme(界面样式)

com.company.projectname.util.theme.XXX

例如:IzPack的菜单UI样式

com.zte.resmaster.util.theme.IzPackMenuUI

 

      1. JNDI名称

EJB注册(可以不用projectname)

Ejb/projectname/ejbtype/EjbnameEJB

例如:

    ejb/resmaster/entity/UserEJB

    ejb/resmaster/session/SecurityEJB

还可以加入子系统名称,以便管理。如:

    ejb/resmaster/baseres/session/QuyuEJB。

可以把ejbtype去掉,如:

    ejb/resmaster/baseres/QuyuEJB。

 

引用EJB

ejb/EjbnameEJB

    例如:

ejb/UserEJB

 

引用数据源(可以使用DatabaseType)

jdbc/DatabaseType/DataSources

例如:jdbc/oracle/ResTxDataSource

  1. 编程规范
    1. 访问类变量和实例

一般不要随意的将变量和实例的访问属性设置为public。

    1. 类变量和方法

不要用一个对象去直接访问类变量或者方法,而是应该用它的类名。例如,

classMethod();            //OK

Aclass.classMethod();      //OK

AnObject.classMethod();    //避免采用

    1. 常量

编码中不应直接使用数字常量,除了在for循环中用的-1,0,1等计数常量。

数字常量又叫Magic Sum,有时你自己都不知道它的值究竟是什么

    1. 变量的声明

避免在一条语句中将一个数值赋给多个变量,这样不易阅读。例如,

   fooBar.fChar = barFoo.lchar = ‘c’;   //应当避免

   不要在语句中容易和“相等”混淆的地方放置操作符。例如,

   if (c++ = d++) {    //JAVA不允许的

       ...

   }

   应当改为,

   if ((c++ = d++) != 0) {

      ...

   }

 

要警惕IF判断语句中的赋值,上面的形式Java编译器拒绝,但是下面的接受:

   boolean flag = false;

   if (flag = booleanexpression){

      ...

   }

    所以,你要清楚你究竟要干什么,不清楚时,写成多行语句

 

另外,不要把一个语句嵌入在另外一个语句中。例如,

   d = (a = b + c) + r    // 避免使用

应该写成,

   a = b + c;

   d = a + r;

    1. 属性(fields)
  1. Field应该设为私有
  2. 不要直接访问属性,应该定义存取成员函数
  3. 不要用常量静态属性(final static fields), 应使用存取成员函数
  4. 不要重名
  5. 静态属性要初始化
    1. Classes
  1. 减少publice和protected 接口的数量
  2. 在编码之前为类定义公共接口
  3. 按照如下顺序声明类属性和成员函数
  1. constructors
  2. finalize()
  3. public member functions
  4. protected member functions
  5. private member functions
  6. private field
    1. 局部变量
  1. 不要命名重复
  2. 每行只能声明一个变量
  3. 局部变量采用行内注释
  4. 紧跟在使用之前定义局部变量
    1. 成员函数
  1. 先进行总体说明注释(document comment)
  2. 将代码安逻辑关系分段
  3. 合理使用空行
  4. 好的成员函数应能够在30秒钟内被其他人理解
  5. 写单行的短注释
  6. 尽可能控制对成员函数内部成员的访问
  7. 说明操作顺序
    1. 避免内存泄漏

由于Java中有内存垃圾收集的机制,并且没有指针类型,开发者就可以从C/C++的内存噩梦中解脱出来。正因为如此,很多开发者就不再关注内存的使用问题。小心,这里存在陷阱。

请注意,Java的这个机制是内存垃圾收集而非内存收集!所以,你需要把使用的对象变成JVM可以识别的垃圾。一般而言,在方法中声明使用的变量在方法外面时就会成为垃圾。但是有些却不是,例如:

   private HashMap dialogMap = new HashMap();

   ...

   {

       JDialog dialog = new JDialog(“XXX”);

      ...

   dialogMap.put(dialog.getTitle(),dialog);

   }

   ...

如果你在整个代码期间都没有调用如下语句:

   Object ref =dialogMap.remove(key);

   ...释放资源,如:((JDialog)ref).dispose()

   ref = null;

或者

   dialogMap.clear()(有时,仅仅这个语句还不行)

那么你的代码就存在内存泄漏问题!

 

几乎所有存储对象的结构都要引起注意,看看是否有资源没有释放,没有成为垃圾而无法回收。下面的对象要严格释放:

java.sql.Connection;

java.sql.Statement;

java.sql.PreparedStatement

java.sql.CallableStatement

java.sql.ResultSet

这些对象如果不释放其资源,不仅仅是内存问题;还将引起数据库问题。如果不释放Connection,那么很快就用尽连接或是数据库巨慢(数据库连接数目还受到Licence的限制)。如果不释放后面的对象资源,那么很快就会用尽数据库游标,因为每打开一次后面的资源就要使用一个游标,即使语句中没有使用游标(其实每个DDL语句都使用一个缺省游标)。而数据库的游标一般是有限制的,Oracle8.1.6中缺省为100,Oracle8.1.7中缺省为300。

千万注意!

可能在一段时间内永远不会碰到内存不足的问题,是不是就不用警惕上面提到的内容呢?

不!

JVM中垃圾内存的收集还受到内存容量的影响。当还有可用内存时,常常不会主动去垃圾收集。这就是为什么常常没有碰到内存不足的问题,因为你机器的内存足够大(256M)。

为了Java程序有序的运行,你可以为它设定一个最大最小内存使用量。就像Weblogic中的一样,如:

-hotspot -ms64m -mx64m。

这样有利于更好的利用垃圾收集机制。

    1. 国际化/本地化处理
      1. 消除硬编码的字符串

妨碍程序国际化的一个常见的设计失误是:把在界面上显示的内容在源代码中进行硬编码,这使得了application或者applet不能被很方便地进行本地化处理。

为了解决这个问题,可以在完成代码的编写和测试以后,把用户界面中的硬编码字符串进行资源化处理,另外的一个较好办法是,在界面设计过程中就对可视的字符串进行资源化处理。

如果使用Jbuilder,就可以使用它所提供的两种方法来完成工作,这两种方法分别是:资源字符串向导(Resource Strings wizard)和本地化属性设置对话框(Localizable Property Setting dialog box)。

如果不使用Jbuilder工具,也可以模仿它所生成的代码,自己进行相应处理。

        1. 使用Resource Strings wizard

Resource Strings wizard能够快速、方便地扫描源代码,把硬编码的字符串放到Java的ResourceBundle类中。

该向导不仅能够处理Jbulider生成的源文件,对于其它来源的Java文件也能处理。

ResourceBundles资源包,是包含有可翻译字符串集合的特殊的文件,

ResourceBundle有两种:PropertyResourceBundle和ListResourceBundle。

PropertyResourceBundles是带有.properties扩展名的文本文件,和源代码生成的class文件在一个目录下。

对于PropertyResourceBundles,在对应用程序的资源包进行修改或者添加时,无需重新编译。

而ListResourceBundles 是以Java源代码文件形式存在的。 由于是以Java源码形式实现的,所以任何新建或者修改的ListResourceBundles,都需要被重新编译才能发布。与PropertyResourceBundles相比,ListResourceBundles的效率要高的多,所以Jbuilder把其作为缺省都选择。

        1. 使用本地化属性设置(Localizable Property Setting)对话框

该属性设置框允许你在创建或者定制用户界面的组件时,就可对可视化的字符串进行资源化处理。

在对象查看器中,右键单击任何text属性字段(比如按钮控件的标签属性)。

然后选择ResourceBundle命令,显示本地化属性设置对话框。

该对话框显示的属性和资源字符串向导对话框中的类似,只是含有影响单个选定对象属性的选项。

在对象查看器中进行资源化处理非常地快速和方便,你完全可以把这个过程看成是对应用程序地组件进行定制的完整步骤之一。

      1. 用户界面设计的国际化
        1. 支持对于Unicode字符的处理

使用Unicode escape序列的16进制值来插入Unicode字符,另外,要用尖括号将其括起来。

比如,要把中文的字符“确定”作为按钮的标签,就可以输入<\u786e\u5b9a>。

        1. 使用动态布局管理

当设计一个将要被本地化为多种语言的用户界面时,最为重要的一个规则是:一定要使用动态布局管理器(dynamic layout manager)。

这可以解决诸如让按钮大小随着它的标签文字的宽度而自动变化等问题。

在实际设计界面时,需要综合考虑、使用Java平台提供的五种最常使用的布局管理方式:BorderLayout, GridLayout ,FlowLayout ,BoxLayout和 GridBagLayout。

        1. 为编译器指定本地编码

编译器对使用本地编码(或者叫本地代码页)的源代码进行编译,这种源码的存储格式被绝大多数的文本编辑器所使用。

编译器会自动根据操作系统环境选择合适的本地代码。也可以为由不同的本地代码写成的源代码文件指定任意的JDK编码。

指定编码的名称,就可以控制编译器解释处理ASCII字符集以外的那些字符。这可以在工程项目范围一级进行指定,也可以在命令行用encoding编译选项来进行控制。如果该选择没有被指定,则会使用平台缺省的本地代码转换器。

      1. 其它要考虑的国际化因素

除了最简单的关于界面显示语言的国际化,还要保证自己的程序对于其它国家相关的特性提供支持,实际应用中的情况是非常复杂的。

其它一些需要考虑的因素包括:提示信息,GUI组件上的标签,在线帮助,声音,颜色,图形,图标,日期,货币符号,数字,小数值,分隔符。。。。。。

此外,一些具体处理过程和方式也会不同,例如排序方法,输入处理等。

这些可以利用java.text包以及java.util包中的TimeZone、SimpleTimeZone和Calendar等类进行辅助处理。

    1. 几个注意点
      1. 括号

通常建议在有多个操作符的表达式中借助于括号来更加清楚地表达一条语句。这能帮助你和其他程序员更好的理解代码。

   if (a == b && c == d)         // 避免

   if ((a == b) && (c == d))     // 较好

      1. 返回值

写代码时应该尽量让你的程序结构很好地体现意图。如:

   if (booleanExpression) {

      return true;

   } else (

      return false;

   )

应该改为如下语句。

   Return booleanExpression;

类似的,

   if (condition) {

      return x;

   }

   return y;

应该写为,

   return (condition ? x : y);

      1. 条件运算中的表达式

如果在三重操作符“?:”中的“?”前面还有二元操作,那么必须采用括号。如,

   (x >= 0) ? x : -x;

 

 

 

  1. 参考书目
  1. Amble S.W. (Feb 2000 ,v17.01d), Writing Robust Java Code, AmbySoft Inc v17.01d, New York ,U.S.A
  2. Perter King, (2001), java Code Conventions, Sun Microsystems, Inc. http://java.sun.com,
  3. 主要参考:张伟民、张立、余勇,(2001-3),《JAVA代码编程规范》;

你可能感兴趣的:(开发语言,JAVA)