JavaEE程序编码规范
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、可以对使用的第三方组件进行独立的安全测试。