Java编码规范526.docx
《Java编码规范526.docx》由会员分享,可在线阅读,更多相关《Java编码规范526.docx(21页珍藏版)》请在冰豆网上搜索。
![Java编码规范526.docx](https://file1.bdocx.com/fileroot1/2023-1/2/ccbc3e14-257d-441e-9d0d-146a73872eed/ccbc3e14-257d-441e-9d0d-146a73872eed1.gif)
Java编码规范526
Java编码规范
1.概述
本标准系公司首次发布实施,主要针对公司所有软件产品源代码范围的Java编码风格,对Java文件的文件组织、代码风格、注释、命名、声明、异常、习惯等方面均做规范,以保障公司项目代码的易维护性和编码安全性。
1.1.术语
●Pascalcase-所有单词第一个字母大写,其它字母小写。
例如:
Person,OrderDetail,OilTank。
●Camelcase-除了第一个单词,所有单词第一个字母大写,其他字母小写。
例如:
oilLevel,customerName。
在后面的描述中我们使用Pascal代表第一种表示方式,Camel代表第二种表示方式。
2.重要规范
2.1.操作规范
2.1.1.模板及格式化
开发人员必须保证代码格式化的一致性,否则可能会导致代码冲突。
轻微的冲突耗费人力合并代码;严重时可能导致代码丢失,引起bug或者故障。
开发人员必须配置cdrundle的codetemplates.xml代码模板文件。
开发人员必须配置cdrundle的cdrundleFormatter.xml代码格式化文件。
每次提交代码之前,必须对java代码format。
模板文件:
Eclipse中配置的位置:
Window->Preferences->Java->Codetemplates
Window->Preferences->Java->Formatter
2.1.2.代码提交
为防止冲突,任何时候,代码(及配置文件)提交前,先从SVN中更新代码和配置文件,以及早发现不兼容的代码变更和冲突。
提交代码(及配置文件)时,如果发生冲突时,先看历史说明,再找相关人员确认,坚决不允许强制覆盖。
每次提交代码之前,必须检查是否有eclipsewarning,并修复所有的warning。
开发过程中定期使用FindBugs扫描代码,合并代码时不允许出现高等级问题。
2.1.3.垃圾清理
对从来没有用到的或者被注释的方法、变量、类、配置文件,动态配置属性等要坚决从系统中清理出去,避免造成过多垃圾。
2.2.日志规范
2.2.1.日志输出
●生产代码禁止以System及Throwable.printStackTrace的方式输出日志信息,必须用Logger替代。
●对trace/debug/info级别的日志输出,必须使用条件输出形式,否则大量的日志会增加来自对象toString的性能成本。
●对于日志的打印,任何情况下都不允许日志错误导致业务失败。
2.2.2.错误日志
对于由于系统原因造成业务处理失败的事件,需要记录错误日志。
非系统原因的业务处理失败,不应该记录错误日志(推荐使用warn级别),避免错误日志过大,影响紧急情况下的故障分析不诊断。
2.3.注释规范
●对于一个完整的类,应该包括Cdrundle的版权注释、类的说明注释、类成员变量注释,以及public、protected、private方法的注释(setter、getter、接口的实现方法除外)。
●必须保证代码和注释的一致性。
●正确区分使用文档注释和实现逻辑注释。
2.4.异常处理
●捕捉到的异常,不允许不做任何处理就截断,至少要记入日志,或重新抛出。
●最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
2.5.安全规范
2.5.1.WEB安全
●对于前台的web页面,必须加上表单防重复提交功能;对于业务关键字段需要加上防篡改的功能,否则可能造成业务重复执行或者被客户端恶意修改。
●对于前台的web页面,严禁出现方便调试的后门页面。
●不允许出现页面向自身重定向、或者多个页面间相互重定向的情况。
如果控制不当,很容易造成系统宕机。
2.5.2.敏感信息的保护
用户的敏感信息包括密码、短信验证码、支付验证码、身份证号、银行卡号、银行密钥,商户密钥等信息,用户敏感信息不能泄露,否则可能会带来不安全因素。
可能会导致敏感信息泄露的方式有:
Logger、URL的get参数(因为URL的get参数会在apache日志中被输出)。
2.6.通用规范
2.6.1.配置信息的使用
避免将UserID、URL、文件名、系统开关参数、业务规则的可变参数等硬编码。
2.6.2.资源的使用
对系统资源的访问,使用后必须释放系统资源。
这类资源包括:
文件流、线程、网络连接、数据库连接等。
●对于文件、流的IO操作,必须通过finally关闭。
●对于线程,线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
●对于网络连接与数据库连接,必须由框架通过连接池提供,不允许应用中自行建立网络与数据库连接。
3.类的编写规范
●所有包、类、接口、方法、属性、变量、参数均使用英文单词进行命名。
●命名包、类、接口、方法以及变量时,尽量使用贴近问题域的且意义丰富的名称。
●修改源代码时,应尽量保持与所修改系统的编码风格保持一致。
●所有包名必须使用com.[company]前缀,所有项目使用com.[company].[projectname],company是公司简称,projectname是项目的缩写。
●注意尽量不要用生僻的缩写,尤其是中文缩写。
4.格式规范
●包的导入应该按照相关性进行分组。
importjava.io.IOException;
import.URL;
importjava.rmi.RmiServer;
importjava.rmi.server.Server;
importjavax.swing.JPanel;
importjavax.swing.event.ActionEvent;
importorg.linux.apache.server.SoapServer;
●只倒入明确需要的类,这样只要看导入列表,就可以知道该类依赖于哪些类和接口,保证可读性。
importjava.util.List;//避免:
importjava.util.*
importjava.util.Arraylist;
importjava.util.HashSet;
●类和接口中元素的布局顺序。
1、类和接口的文档描述
2、类和接口的声明
3、类的静态变量,按照public,protected,package,private的顺序。
4、实例变量,按照public,protected,package,private的顺序。
5、类的方法,无固定顺序。
●类的声明,基类和实现的接口应该独立成行,保证可读性。
classUserManagerImpl
extendsAbstractManager
implementsIUserManager{
…
}
●方法修饰关键字定义顺序。
staticabstractsynchronized
unuaualfinalnativemethodName
注意访问标示符一定要在最前面。
publicstaticdoublesquare(doublea);
//避免:
staticpublicdoublesquare(doublea);
●变量声明,采用Camel表示法不要在一行声明多个变量。
//推荐
intlevel;
intsize;
//避免
intlevel,size;
●保证明确的类型转换,不要默认进行隐式类型转换
intValue=(int)floadValue;//避免intValue=floatValue
●数组指示符紧跟类型变量
int[]a=newint[20];//避免:
inta[]=newint[20]
一个变量要代表独立的意思,不要在其生命周期赋予它不同的概念。
inttempValue;
tempValue=maxValue;
…
…
tempValue=minValue;
…
tempValue=anotherValue;
tempValue在生命周期内表示了各种各样的意图,增加理解代码的难度。
应该为每个独立概念定义单独的变量:
inttempMaxValue;
inttempMinValue;
inttempAnotherValue;
●仅仅循环控制变量才能出现在for()循环中
sum=0;
for(i=0;i<100;i++){
sum+=value[i];
}
//避免:
for(i=0,sum=0;i<100;i++){
sum+=value[i];
}
●循环变量应靠近循环体初始化
isDone=false
while(!
isDone){
…
}
//避免
isDone=false;
…
…
while(!
isDone){
…
}
●避免长的布尔表达式,应换成多个更容易理解的表达式。
boolisFinished=(elementNo<0)||(elementNo>maxElement);
boolisRepeatedEntry=elementNo==lastElement;
if(isFinished||isRepeatedEntry){
…
}
//避免
if((elementNo<0)||(elementNo>maxElement)||elementNo==lastElement){
…
}
●不要在条件语句中执行方法,以提高可读性
InputStreamstream=File.open(fileName,"w");
if(stream!
=null){
…
}
//避免
if(File.open(fileName,"w")!
=null)){
…
}
●代码缩进,应该使用4个空格为一个单位进行缩进。
publicStringinvoke()throwsException{
....StringprofileKey="invoke:
";
try{
....UtilTimerStack.push(profileKey);
if(executed){
....test=true;
}
catch{
}
}
●条件语句的主要形式,即使单条语句,也要使用括号括起来。
if(condition){
statements;
}
if(condition){
statements;
}else{
statements;
}
if(condition){
statements;
}elseif(condition){
statements;
}else{
statements;
}
●空循环体也要使用完整的{}块
for(initialization;condition;update){
;
}
●switch语句的使用格式
switch(condition){
caseABC:
statements;
//穿透,一定要做出注释
caseDEF:
statements;
break;
caseXYZ:
statements;
break;
default:
statements;
break;
}
●try-catch使用格式
try{
statements;
}
catch(Exceptionexception){
statements;
}
try{
statements;
}
catch(Exceptionexception){
statements;
}
finally{
statements;
}
●空格的使用
1、运算符两边应该各有一个空格。
2、Java保留字后面应跟随一个空格。
3、逗号后面应跟随一个空格。
4、冒号两个应各有一个空格。
5、分号后面应跟随一个空格。
a=(b+c)*d;//NOT:
a=(b+c)*d
while(true){//NOT:
while(true){
...doSomething(a,b,c,d);//NOT:
doSomething(a,b,c,d);
case100:
//NOT:
case100:
for(i=0;i<10;i++){//NOT:
for(i=0;i<10;i++){...
●逻辑上紧密相关的代码块应该用一个空行分开。
//Createanewidentitymatrix
Matrix4x4matrix=newMatrix4x4();
//Precomputeanglesforefficiency
doublecosAngle=Math.cos(angle);
doublesinAngle=Math.sin(angle);
//Specifymatrixasarotationtransformation
matrix.setElement(1,1,cosAngle);
matrix.setElement(1,2,sinAngle);
matrix.setElement(2,1,-sinAngle);
matrix.setElement(2,2,cosAngle);
//Applyrotation
transformation.multiply(matrix);
●为了保证可读性,变量名应该左对齐。
TextFilefile;
intnPoints;
doublex,y;
//避免
TextFilefile;
intnPoints;
doublex,y;
●像前面一般规则里说的那样,任何提高代码可读性的排版都可以去尝试,下面是一些例子。
if(a==lowValue)compueSomething();
elseif(a==mediumValue)computeSomethingElse();
elseif(a==highValue)computeSomethingElseYet();
value=(potential*oilDensity)/constant1+
(depth*waterDensity)/constant2+
(zCoordinateValue*gasDensity)/constant3;
minPosition=computeDistance(min,x,y,z);
averagePosition=computeDistance(average,x,y,z);
switch(phase){
casePHASE_OIL:
text="Oil";break;
casePHASE_WATER:
text="Water";break;
casePHASE_GAS:
text="Gas";break;
}
●当对if语句中的条件进行折行时,应该使折行的条件语句相对主功能语句再行缩进4个空格,以突出主要功能语句。
//使用这种缩进,突出主要功能语句。
if((condition1&&condition2)
||(condition3&&condition4)
||!
(condition5&&condition6)){
doSomethingAboutIt();
}
//避免使用这种缩进,主功能语句不突出。
if((condition1&&condition2)
||(condition3&&condition4)
||!
(condition5&&condition6)){
doSomethingAboutIt();
}
●三元条件运算符可以使用如下三种表达方式,条件要用括号括起来。
alpha=(aLongBooleanExpression)?
beta:
gamma;
alpha=(aLongBooleanExpression)?
beta
:
gamma;
alpha=(aLongBooleanExpression)
?
beta
:
gamma
5.命名规范
5.1.一般命名规范
●包名应该用小写字母,不要出现下划线等符号,名词用有意义的缩写或者英文单词。
示例:
//推荐
com.cdrundle.normativefile.dao
java.lang.util
//避免
com.Esse-tech.buSiness
●所有类命名使用Pascal表示方式,使用名词组合。
UserManager,ClassLoader,HttpHeaderResult
●接口命名使用字母“I”加上Pascal形式的表示方式。
IQuery,IDataAccess,IReportBuilder
●使用名词组合或形容词去命名一个接口,接口声明了一个对象能提供的服务,也描述了一个对象的能力。
一般以“able”和“ible”作为后缀,代表了一种能力。
publicinterfaceRunnable{
publicvoidrun();
}
publicinterfaceAccessible{
publicContextgetContext();
}
●变量名和参数名使用Camel表示方式。
userName,objectFactory,entrys,list
●对于常量名,使用大写字母,并使用下划线做间隔。
MAX_TIMES,DEFAULT_NAME程序中应该使用常量代替“25”,“100”等实际的数字,如:
//推荐
if(times==MAX_TIMES){
…
}
//避免
if(times==25){
…
}
这样做的好处是,当因需要修改实际的数字时,比如修改25为30,只需要修改一处。
●方法名应该使用动词开头,使用Camel表示方式,一般由动词+名词组成。
getName,initialize,addParameter,deleteUser
●缩写字母也应该保持首字母大写
exportHtmlSource();//避免:
exportHTMLSource();
openDvdPlayer();//避免:
openDVDPlayer();
●变量的名字应该和类型名称一致
voidsetTopic(Topictopic)//避免:
voidsetTopic(Topicvalue)
//避免:
voidsetTopic(TopicaTopic)
//避免:
voidsetTopic(Topict)
voidconnect(Databasedatabase)
//避免:
voidconnect(Databasedb)
//避免:
voidconnect(DatabaseoracleDB)
当同时定义多个属于同一个类的变量时,把类型作为实例的后缀,如:
PointstartPoint;
PointcenterPoint;
这样做是为了从实例名就可以推断它的类型名称。
●根据变量的作用范围,作用范围大的应该使用长名称,作用范围大,表明变量的生命周期比较长,为了有助于理解,应尽量用长名称以表达变量的真实意图。
反之,对于作用范围小,可以使用一些简化的名称,比如i,j,k等,提高编程效率。
for(inti=0;i…
}
5.2.特殊命名规范
●使用get/set对类属性进行访问,这是Java社区的核心编码规范。
●使用is前缀表示一个布尔变量和方法。
isUsed,isEmpty,isVisible,isFinished
有时也可以使用has,can,should:
booleanhasLicense();
booleancanEvaluate();
booleanshouldAbort=false;
●在查询方法中应使用find作为前缀
vertex.findNearestVertex();
matrix.findSmallestElement();
node.findShortestPath(NodedestinationNode);
●使用initialize作为对象初始化的方法前缀,也可以简写为init
initializeFiles();
init();
initFontSet();
●对于对象集合,变量名称应使用复数。
Collectionpoints;
int[]values;
●对于抽象类,应该使用Abstract前缀。
AbstractReportBuilder,AbstractBeanFactory
●对于表示编号的变量,应加No后缀。
tableNo,userNo,employeeNo
●常在一起使用的对称词汇,这些词汇一起使用,方法的表达意图自然可以互相推测和演绎。
get/set,add/remove,create/destroy,start/stop,insert/delete,increment/decrement,begin/end,first/last,up/down,min/max,next/previous,old/new,open/close,show/hide,suspend/resume
●避免使用否定布尔变量
boolisError;//避免:
isNoError
boolisFound;//避免:
isNotFound
●异常类应该使用Exception作为后缀。
AccessException,RuntimeException
●缺省接口实现应该使用Default前缀
classDefaultTableCellRendererimplementsTableCellRenderer{
…
}
●对于单例类(Singleton),应该使用getInstance方法得到单例。
classUnitManager{
privatefinalstaticUnitManagerinstance=newUnitManager();
privateUnitManager(){
...
}
publicstaticUnitManagergetInstance(){
returninstance;
}
}
●对于工厂类,进行创建对象的方法,应该使用n