JavaEE程序编码规范

时间:2022-08-21 15:20:38

JavaEE程序编码规范

目   录

JAVA程序编码规范1

1变量的命名规则1

1.1常量(包含静态的)1

1.2类变量(静态变量)及实例变量1

1.3局部变量1

1.4参数2

1.5其它2

2方法的命名规则3

3类及接口的命名规则3

3.1一般类名3

3.2值对象3

3.3Action3

3.4MyBatis配置文件4

3.5DAO4

3.6Application Service4

3.7工具类4

3.8门面类4

3.9代理类4

3.10异常类4

3.11接口类5

3.12接口实现类5

4作用域5

4.1类的作用域5

4.2方法的作用域5

4.3属性的作用域5

4.4局部变量的作用域5

5注释的编写规则6

6格式7

6.1缩进7

6.2每代码行的长度7

6.3大括号8

6.4空行8

6.5空格9

6.6import部分9

6.7数字9

7性能与安全10

7.1静态检查插件10

7.2空指针引用(null pointer dereference)10

7.3数组引用问题(RETURN ARRAY)10

7.4硬编码敏感数据(Hard-coded sense data)10

7.5整数溢出10

7.6对象初始化10

7.7集合对象初始化容量11

7.8简单参数11

7.9Final类和方法11

7.10无用的代码11

7.11日志级别11

7.12序列化问题11

7.13通过名称比较类12

7.14类克隆12

7.15JDBC使用13

7.16SQL语句13

7.17数据库连接释放13

7.18使用存储过程13

7.19第三方组件14

8附件14

1 变量的命名规则

1.1 常量(包含静态的)

一个或多个英文单词的组合,所有字母均大写,单词之间以“_”分隔,如:

public static final String UPDATE_FLAG = “T”;

final double PI = 3.14;

一般情况下常量的public等修饰符不可少。

1.2 类变量(静态变量)及实例变量

一个或多个英文单词的组合,第一个单词的首字母小写,其他单词首字母均大写,其余所有字母均小写。如:

private ProjectSes projectSes;

private static String providerUrl = “http://127.0.0.1”;

private Logger logger = Logging.getLogger("TestLogger");

一般情况下类变量(静态变量)及实例变量的public等修饰符不可少。

1.3 局部变量

一个或多个英文单词的组合,一般采用Hungaryn naming法(匈牙利定义法),如下:

以下是基本数据类型的前缀列表

前缀

含义

实例

ch

表示char类型

char chTemp;

i

表示int类型

int iNumber;

byte

表示Byte类型

byte byteGet;

s

表示short类型

short sNumber;

l

表示long类型

long lNumber;

f

表示float类型

float fCount;

d

表示double类型

double dPrise;

str

表示String类型

String strSend;

b

表示boolean类型

Boolean bFlag;

其他数据类型的前缀列表

前缀

含义

实例

col

表示Collection类型

Collection colUser = new ArrayList();

Collection colUser = new Vector();

lst

表示List类型

List lstUser = new ArrayList();

date

表示Date类型

Date dateStart = new Date();

sb

表示StringBuffer类型

StringBuffer sbName= new StringBuffer(1024)

除上述情况以外的数据类型,都以obj作为前缀,后面跟一个能说明变量功能或意义单词作为变量,如:

UserVO objUserVO;

1.4 参数

一个或多个英文单词的组合,第一个单词的首字母小写,其他单词首字母均大写,其余所有字母均小写。如:

public void setProjectVO(ProjectVO projectVO)

public void setUserId(String userId)

建议方法的参数不要超过5个,超过时可以将多个参数合并为一个对象进行传递。

1.5 其它

Ø 常用数据类型的变量,采用固定的命名,包括以下几种:

Connection conn;

ResultSet rs;

PreparedStatement pstmt;

Statement stmt;

Ø 数组变量命名与普通变量命名规则一致,如:

int iProjectId[];

public String userName[];

Ø 每个变量的声明单独占一行。不能一个类型同时声明两个变量。如:int i, j; 这样的写法是不允许的。

Ø 不要在代码中出现不使用的变量,如果以后会用到或有其他用途要写上注释说明。

Ø 类名、变量名中含缩写词组:缩写词组全部大写,如:

String strSQL;

public class ProjectDAO{

}

2 方法的命名规则

Ø 方法命名的基本原则:容易看懂

Ø 一般的方法名采用两个单词动宾结构形式的名称,两个单词之间不要带其它符号,第二个单词的首字母大写,其它的都小写。

如:readBudget(int budgetId)、deleteBudget(int budgetId)

Ø 只有一个动词形式的方法名不推荐使用。

Ø 不容易看明白的方法名或有歧义的方法名可采用多单词的形式,每两个单词之间不要带其它符号,从第二个单词开始,每个单词的首字母大写,其它的都小写。

如:readBudgetByProjectId(int projectId)、readBudgetByProjectIdAndYear(int projectId,int year)

Ø 方法命名不得采用缩写形式。

3 类及接口的命名规则

3.1 一般类名

一个或多个英文单词的组合,所有单词的首字母大写,其余所有字母均小写,如:

public class ProjectUser {

}

3.2 值对象

数据库表的逻辑名+VO,如:

表PUB_DICTIONARY的值对象名为DictionaryVO。

3.3 Action

表名/模块名+Action,如:

字典的Action类名为DictionaryAction。

3.4 MyBatis配置文件

表名/模块名+SQL.xml,如:

字典模块的MyBatis配置文件命名为DictionarySQL.xml。

3.5 DAO

DAO类名为模块名+DAO,如:

字典DAO类名为:DictionaryDAO

3.6 Application Service

Application Service类名为模块名+AppService,如:

字典Application Service类名为:DictionaryAppService

3.7 工具类

工具类的类名为模块名+Util,如:

字典的工具类名为:DictionaryUtil

3.8 门面类

门面类的类名为模块名+Facade,如:

字典的门面类名为:DictionaryFacade

3.9 代理类

代理类的类名为模块名+Man,如:

字典的代理类名为:DictionaryMan

3.10 异常类

异常类的类名为模块名+Exception,如:

字典的异常类名为:DictionaryException

3.11 接口类

接口类的类名为模块名+Interface,如:

字典的接口类名为:DictionaryInterface

3.12 接口实现类

接口实现类的类名为实现名+Imp,如:

字典的接口实现类名为:DictionaryImp

4 作用域

4.1 类的作用域

Ø 类的作用域保持最小范围。供包外其它类引用的类才添加public作用域修饰符。

4.2 方法的作用域

Ø 只供对象或类内部调用的方法必须使用private作用域修饰符。

Ø 包外不会调用的方法严禁使用public作用域修饰符。

4.3 属性的作用域

Ø 静态常量(类常量)属性可以使用各种作用域修饰符。

Ø 对象属性变量严禁使用public作用域修饰符。

Ø VO对象属性变量必须使用private作用域修饰符。

4.4 局部变量的作用域

Ø 方法内的变量定义应该遵循最小作用域规则。

如:

// iSize只在下面的for循环中使用

int iSize = alItems.size();

for(int i=0;i<iSize;i++){

……………………………….

}

建议写成:

for(int i=0,iSize = alItems.size();i<iSize;i++){

……………………………….

}

Ø 属性是对象的特征,不要把非对象的属性定义为实例变量。

5 注释的编写规则

所有类及接口文件要写文件头注释(包含版权等),版权中的年度代码书写的开始年度(Copyright (C) 2011),如下:

/******************************************************************************

* Copyright (C) 2011 SunLine Information Technology Co.,Ltd

* All Rights Reserved.

* 本软件为SunLine开发研制。未经本公司正式书面同意,其他任何个人、团体不得使用、

* 复制、修改或发布本软件.

*****************************************************************************/

所有类及接口头要写类注释(包含作者、创建日期等),@author、@history中要书写中文名,如果注释的内容比较长则需要加“<br>”。如下:

/**

* 技改项目业务代表实现类.实现新增项目,删除项目等方法,<br>

* 提供对表现层的接口.

* @author  张三

* @since   JDK1.4

* @history 2004-10-15 张三 新建

*/

类中必要的方法(包括私有方法)要写方法头注释。其中返回值(@return)需要说明含义,包括整型,布尔型,集合等,如对于整形:@return 返回1表示成功,0表失败;对于集合类型要写明集合内元素的类型:@return UserVO的集合。如果注释的内容比较长则需要加“<br>”,如下:

/**

* 修改投标人信息

* @param bidderVO 投标人信息

* @throws BidderException 修改异常

* @throws NoPermissionException 没有修改权限

* @return 修改成功返回1 没有修改返回0

*/

public int updateBidder(BidderVO bidderVO) throws BidderException

对代码块的注释,注释语句放在代码块之上,用”//”进行注释,如果注释语句本身超过一行,则用”/* */”进行注释。

对某一行代码的注释,注释语句放在代码行的后面,用”//”进行注释。

建议代码块之间空一行。如下:

public void insertProject(ProjectVO projectVO) {

// 新增项目信息

iProjectId = Toolkit.getInstance().getNextKey("Project"); // 取项目ID

logger.debug("Generate Project ID : " + iProjectId);

Project objProject = projectHome.create(iProjectId);

objProject.setProjectVO(projectVO);

<空一行>

/*

从项目VO中取得申请人ID及联系人ID,

并将申请人ID及联系人ID插入到PUB_ACCESS_CONTROL表

*/

projectVO.setProjectId(iProjectId);

this.authProject(projectVO);

}

6 格式

引入公司指定的格式化配置文件最新版本,使用Eclipse的格式化功能进行代码格式化。

6.1 缩进

设定为4 个字符。

6.2 每代码行的长度

代码行的长度不超过120个字符。

6.3 大括号

大括号中的“{”与条件在同一行,“}”单独一行,即使大括号中只有一条执行语句也要使用大括号,如:

if (a == b) {

return 0 ;

}

6.4 空行

类文件头注释、package语句、import语句、类头注释、类的属性、方法等之间都空一行。

类的属性与属性之间、方法与方法之间都空一行。

如下:

/******************************************************************************

* Copyright (C) 2011 SunLine Information Technology Co.,Ltd

* All Rights Reserved.

* 本软件为SunLine开发研制。未经本公司正式书面同意,其他任何个人、团体不得使用、

* 复制、修改或发布本软件.

*****************************************************************************/

<空一行>

package com.comtop.app.project.projectinfo.exception;

<空一行>

import com.comtop.util.BaseException;

<空一行>

/**

* 公共项目管理异常类.

* @author  张三

* @since   JDK1.4

* @history 2005-03-15 张三 新建

*/

public class ProjectException extends BaseException {

private String message;

<空一行>

/**

... ...

*/

public ProjectException(String message) {

super(message);

this.message = message;

}

<空一行>

/**

... ...

*/

public String getMessage() {

return message;

}

}

6.5 空格

“=”、“+”、“==”等二元操作符两边分别空一格。如:

int i = 1;

“,”的后面空一格。如:

implements Runnable, cloneable

6.6 import部分

import引用要具体到类名,不能用“*”。

import语句书写的顺序为:Java标准类,第三方软件类库,本公司自己的组件类、本工程其他包中的类。这四部分之间分别空一行。所有需要用到的其他包的类都要在import中应用,不要将类似“new java.util.ArrayList()”的语句写在代码中。

6.7 数字

long、double、float型变量后的字母“L”、“D”、“F”均大写。16进制的前缀“0X”要大写“X”,数字部分“A”à“F”要大写。

代码中不要直接使用数字(-1,0,1除外),要先对数字进行变量声明。

7 性能与安全

7.1 静态检查插件

有tptp-analysis、PMD、findbugs、checkStyle、commontools共5个插件做为代码自检的标准工具。按照给定的最新版插件配置文件检查,识别问题原因及改进范围,在上传配置库前改进代码格式及性能。

7.2 空指针引用(null pointer dereference)

在使用或引用对象前,要先对其进行检查,判断其是否为空。

7.3 数组引用问题(RETURN ARRAY)

不要直接返回指向包含敏感数据的内部数组的引用。不要传回一个数组,而是数组的拷贝。

7.4 硬编码敏感数据(Hard-coded sense data)

应该将敏感数据保存在属性文件中,无论什么时候需要这些数据,都可以从该文件读取。如果数据极其敏感,那么在访问属性文件时,应用程序应该使用一些加密/解密技术,避免导致敏感数据泄露。

7.5 整数溢出

应该对所有整数计算的结果进行检查,防止整数溢出。

7.6 对象初始化

对变量的使用不要依赖于初始化。在使用对象之前,应该检查对象的初始化过程。可以采用如下方法实现:

在每个类中都应该有一个在构造器中设置的私有布尔标志,在每个非 static 方法中,代码在任何进一步执行之前都应该检查该标志的值。如果该标志的值为 true ,那么控制应该进一步继续;否则,控制应该抛出一个例外并停止执行。

7.7 集合对象初始化容量

在初始化StringBuffer、集合类(List、Set、Map)等时,一般要指定对象的初始化容量,避免不必要的空间浪费,提升性能。

StringBuffer的初始化容量比PMD插件检查后给出的建议值大一些的值;

List、Set初始化容量可设置为估计值;

Map初始化容量可设置为估计值的2倍到3倍。

7.8 简单参数

方法调用时,传入的参数应该是一个具体对象,而不是一个嵌套另一个方法。比如类似“this.a(b(c()))”,要将方法的返回值赋给变量再作为参数传递。

7.9 Final类和方法

应该将不允许扩展的类和方法应该声明为 final,这样可以防止系统外的代码扩展类并修改类的行为。

避免使用非final的公共静态变量。

7.10 无用的代码

应该将(除启动应用程序的 main() 方法之外的) main() 方法、未使用的方法以及死代码从应用程序代码中除去。

调试使用的控制台输出语句(System.out.println)在调试结束后要删除。

7.11 日志级别

使用正确的日志级别输出,注意info、warning、debug、error等级别的使用场合。禁止使用debug级别输出错误信息,禁止使用errror级别输出调试信息。

7.12 序列化问题

在包含系统资源的直接句柄和相对地址空间信息的字段前应该使用transient关键字。如果资源,如文件句柄,不被声明为transient,该对象在序列化状态下可能会被修改,从而使得被反序列化后获取对资源的不当访问。

为了确保反序列化对象不包含违反一些不变量集合的状态,类应该定义自己的反序列化方法并使用ObjectInputValidation接口验证这些变量。

为了保护虚拟机外的字节流,可以对序列化包产生的流进行加密。字节流加密防止解码或读取被序列化的对象的私有状态。如果决定加密,应该管理好密钥,密钥的存放地点以及将密钥交付给反序列化程序的方式等。

如果一个类定义了自己的序列化方法,它就不能向任何DataInput/DataOuput方法传递内部数组。所有的DataInput/DataOuput方法都能被重写。注意默认序列化不会向DataInput/DataOuput字节数组方法暴露私有字节数组字段。

7.13 通过名称比较类

在那些非得根据名称来比较类的情况下,必须确保使用了当前类的 ClassLoader 的当前名称空间,如下面示例中所示的一种更好的比较方法:

if(obj.getClass()== this.getClassLoader().loadClass("com.bar.Vnet")){

// object's class is equal to

//the class that this class calls "com.bar.Vnet"

}else{

// object's class is not equal to the class that

// this class calls "com.bar.Vnet"

}

比较类的更好方法是直接比较类对象看它们是否相等:

if(a.getClass() == b.getClass()){

// objects have the same class

}else{

// objects have different classes

}

应该尽可能少用直接名称比较。

7.14 类克隆

除非有明确的需求,否则要保证你定义的类是不可克隆的。要使类不可被复制,只要在每个类里定义如下方法:

public final Object clone()‏

throws java.lang.CloneNotSupportedException{

throw new java.lang.CloneNotSupportedException();

}

如果想让您的类可克隆并且您已经考虑了这一选择的后果,请在你的类中定义一个为 final 的克隆方法

public final Object clone()‏

super.clone();

}

7.15 JDBC使用

SQL语句变量使用“?”绑定变量。在DAO中,所有SQL语句中的变量都要使用“?”来绑定变量,禁止直接拼凑变量到SQL语句中;

查询分页数据方法中,避免取所有记录的方式。在DAO中,查询分页数据的方法,不得使用取所有记录出来后再分页的方式,而要使用分页SQL语句包装方法。

SQL语句不得在DAO外书写。不得在DAO类外写好SQL语句后传入DAO执行。

查询数据集合时要使用DAO方式,避免使用EntityBean查询数据集合。

7.16 SQL语句

l 类中包含的SQL语句必须全部大写(包括关键字、表名、字段名等),如:

SELECT PROJECT_NAME FROM IMP_PROJECT WHERE PROJECT_ID = 1

l EJB的EJB-QL中关键字(如WHERE等)必须全部大写, 实体类的别名为英文单词(组合)且单词首字母大写,其余字母全部小写。如:

SELECT OBJECT(User) FROM User AS User WHERE User.Id= ?1

7.17 数据库连接释放

数据库访问可使用EJB的EntityBean等,对数据集的访问必须使用DAO方式。

不管代码是否失败,均关闭对数据库的连接。DAO层可使用iBatic等开源框架,如果是手工写SQL语句访问,必须在try语句的finilly块中安全释放数据库连接。

7.18 使用存储过程

对于复杂的数据库操作应该使用存储过程。

存储过程具有更短运行时间和更短的事务锁,具有更高的运行效率。

7.19 第三方组件

慎重使用第三方组件。

如果必须使用第三方组件,那必须遵守以下原则:

1、向你要重用的提供商询问,是否用过findbugs或者类似的工具检查组件,确保供应商进行过足够的安全测试。

2、在你购买之前要求一个findbugs的报告,这可能增加对组件的信任

3、可以对使用的第三方组件进行独立的安全测试。

8 附件

JavaEE程序编码规范