JAVA编码规范V10要点Word文件下载.docx
《JAVA编码规范V10要点Word文件下载.docx》由会员分享,可在线阅读,更多相关《JAVA编码规范V10要点Word文件下载.docx(24页珍藏版)》请在冰豆网上搜索。
3JAVA规范
3.1构建
R1Java项目均应采用maven进行项目构建,并能实现通过命令行自动构建。
说明:
采用Maven或Gradle进行项目构建是Java项目开发工作自动化的常见选项。
Gradle目前普及程度不及Maven。
故此公司决定采用Maven作为项目构建的基础工具。
未来推广自动构建、持续集成、代码自动审查等工作,均依赖于项目最基础的标准化工作。
希望大家遵守。
3.2代码架构
S1如果类在当前定义文件外被使用,则需要定义为public
Java强制要求每个Java文件中有一个public类型的类。
因此,public类和Java文件具有一一对应关系。
这背后隐含着Java语言推荐的代码组织规则。
我们在编码过程中,也应尽量遵循该规则,避免非public类在当前定义文件外被使用的情况。
如果需要被当前定义文件外的类使用,请声明为public,以增加代码可读性。
3.3排版
R1程序块要采用缩进风格编写,代码缩进单位为4个空格,不使用Tab缩进。
说明:
缩进使程序更易阅读,由于开发工具及开发操作系统环境统一,所以不使用Tab缩进。
【注】采用Tab键和space键进行缩进是经常发生争议的地方。
毫无疑问Tab键缩进的便利性远超space键。
但是考虑到常用的代码审查工具都建议采用space而不是tab缩进。
因此,为了未来代码格式化和代码审查的方便,规定采用空格缩进的方式。
可在开发工具中设置采用4个空格键替换Tab
R2左分界符(如大括号‘{’)应在语句同一行,并与语句间隔一个空格,右分界符(如大括号‘}’)独占一行,同时与引用它们的语句左对齐。
在函数体的开始、类和接口的定义、以及if、for、do、while、switch、case语句中的程序或者static、,synchronized等语句块中都要采用如上的缩进方式。
示例:
if(a>
b){
doStart();
}
R3每行语句字符不超过100字符,对于较长的语句、表达式或参数要分成多行书写,换行应遵循逗号后面,操作符前面的原则。
示例:
if(logger.isDebugEnabled()){
logger.debug("
Sessiondestroyed,call-id"
+event.getSession().getCallId());
}
R4不允许把多个短语句写在一行中,即一行只写一条语句。
阅读代码更加清晰
如下例子不符合规范。
Objecto=newObject();
Objectb=null;
R5if,for,do,while,case,switch,default等语句自占一行,且if,for,do,while,switch等语句的执行语句无论多少都要加括号{},case的执行语句中如果定义变量必须加括号{}。
阅读代码更加清晰,减少错误产生
casex:
{
inti=9;
【注】这里需要特别说明的是一种被称作ifthen的情况。
R6在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;
进行非对等操作时,如果是关系密切的立即操作符(如.),后不应加空格。
阅读代码更加清晰
if(a==b){
objectA.doStart();
a*=2;
S1类属性和类方法不要交叉放置,不同存取范围的属性或者方法也尽量不要交叉放置。
格式:
类定义{
类的静态属性定义
类的静态方法定义
类的私有属性定义
类的保护属性定义
类的公有属性定义
类的私有方法定义
类的保护方法定义
类的公有方法定义
S2修饰词按照指定顺序书写:
[访问权限][static][final]。
publicstaticfinalStringstr=“abc”;
S3可以使用MyEclipse或Eclipse自带的ctrl+shift+F来自动格式化编码排版,格式化后请认真检查一下。
注意如果使用搜狗输入法,请确认与其快捷键不冲突,详细参照:
3.4注释
R1类和接口的注释放在class或者interface关键字之前,import关键字之后。
注释主要是功能简述。
类注释使用“/***/”注释方式。
类和接口注释要着重功能描述、作者、交付后修改记录。
/**
*〈功能简述〉
*@author[作者](必须)
*/
packagem;
importjava.util.Date;
*LogManager类集中控制对日志读写的操作。
*@author张三,李四,王五
publicclassLogManager
R2类属性(成员变量)、公有和保护方法注释:
写在类属性、公有和保护方法上面,注释方式为“/***/”。
*注释内容
*/
privateStringlogType;
publicvoidwrite()
R3公有和保护方法注释内容:
列出方法的一句话功能简述、功能详细描述、输入参数、输出参数、返回值、异常等。
*@param[参数1][参数1说明]
*@param[参数2][参数2说明]
*@return[返回类型说明]
*@exception/throws[异常类型][异常说明]
/**
*根据日志类型和时间读取日志。
*分配对应日志类型的LogReader,指定类型、查询时间段、条件和反复器缓冲数,
*读取日志记录。
查询条件为null或0的表示没有限制,反复器缓冲数为0读不到日志。
*查询时间为左包含原则,即[startTime,endTime)。
*@paramlogTypeName日志类型名(在配置文件中定义的)
*@paramstartTime查询日志的开始时间
*@paramendTime查询日志的结束时间
*@paramlogLevel查询日志的级别
*@paramuserName查询该用户的日志
*@parambufferNum日志反复器缓冲记录数
*@return结果集,日志反复器
publicstaticLogIteratorread(StringlogType,DatestartTime,DateendTime,intlogLevel,StringuserName,intbufferNum)
R4对于方法内部用throw语句抛出的异常,必须在方法的注释中标明,对于所调用的其他方法所抛出的异常,选择主要的在注释中说明。
对于非RuntimeException,即throws子句声明会抛出的异常,必须在方法的注释中标明。
异常注释用@exception或@throws表示,在JavaDoc中两者等价,但推荐用@exception标注Runtime异常,@throws标注非Runtime异常。
异常的注释必须说明该异常的含义及什么条件下抛出该异常。
R5注释应与其描述的代码相近,对代码的注释应放在其上方,并与其上面的代码用空行隔开,注释与所描述内容进行同样的缩排。
可使程序排版整齐,并方便注释的阅读与理解。
*注释
publicvoidexample2(){
//注释
CodeBlockOne
CodeBlockTwo
publicvoidexample(){
R6修改代码同时修改相应的注释,以保证注释与代码的一致性。
R7避免在注释中使用缩写,特别是不常用缩写。
在使用缩写时或之前,应对缩写进行必要的说明。
R8对重写父类的方法必须进行@Override声明。
可清楚说明此方法是重写父类的方法,保证重写父类的方法时不会因为单词写错而造成错误(写错方法名或者参数个数,类型都会编译无法通过)
@Override
publicvoiddoRequest(SipServletRequestreq)throwsServletException,
IOException
R9对于需要注释掉(不使用)的代码,应使用//注释,而不是/**/注释
考虑到对SCM系统(SVN等)的友好,注释掉的代码段,应采用//而不是/**/,因为采用/**/注释,修改的代码行只有首位两行,中间的代码段无任何变化。
这样svn工具无法判断出实际所做的修改。
而通过//注释的代码,必须逐行注释,在svn工具中可以很容易判断出整个被注释掉的代码段。
这对于依赖svn等SCM系统进行代码审查的工作来说,是很有价值的。
S1在代码的功能、意图层次上进行注释,提供有用、额外的信息。
注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息。
如下注释意义不大。
//如果receiveFlag为真
if(receiveFlag)
而如下的注释则给出了额外有用的信息。
//如果从连结收到消息
【注】这一条存在争议。
按照目前比较主流的思路。
代码本身应该是具有自解释能力。
通过使用约定俗成的设计模式、命名规范和代码格式,经验丰富的代码编写和阅读者能够顺利的读懂代码,不需要太多注释。
甚至可以认为,注释写的过多,说明代码的逻辑和可读性可能存在问题。
同时,需要注意的一点是:
不要将注释等同于文档。
注释可以简练精致甚至不写。
但对类、方法的描述属于文档层面,其重要性和必要性不应存在争议。
S2对关键变量的定义和分支语句(条件分支、循环语句等)编写注释。
这些语句往往是程序实现某一特定功能的关键,对于维护人员来说,良好的注释帮助更好的理解程序,有时甚至优于看设计文档。
注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,除非能用非常流利准确的英文表达。
中文注释中需使用中文标点。
方法和类描述的第一句话尽量使用简洁明了的话概括一下功能,然后加以句号。
接下来的部分可以详细描述。
注释语言不统一,影响程序易读性和外观排版,出于对维护人员的考虑,建议使用中文。
JavaDoc工具收集简介的时候使用选取第一句话。
S3一些复杂的代码需要说明。
这里主要是对闰年算法的说明。
//1.如果能被4整除,是闰年;
//2.如果能被100整除,不是闰年;
//3.如果能被400整除,是闰年。
3.5命名
R1类名和接口使用意义完整的英文描述,每个英文单词的首字母使用大写、其余字母使用小写的大小写混合法。
(Pascal命名法)
OrderInformation,CustomerList,LogManager,LogConfig,SmpTransaction
R2方法名使用类意义完整的英文描述:
第一个单词的字母使用小写、剩余单词首字母大写、其余字母小写。
(驼峰命名法)
privatevoidcalculateRate();
publicvoidaddNewOrder();
R3方法中,存取属性的方法采用setter和getter方法,动作方法采用动词和动宾结构。
get+非布尔属性名()
is+布尔属性名()
set+属性名()
动词()
动词+宾语()
publicStringgetType();
publicbooleanisFinished();
publicvoidsetVisible(boolean);
publicvoidshow();
publicvoidaddKeyListener(Listener);
R4属性名使用意义完整的英文描述,第一个单词的字母使用小写,剩余单词首字母大写其余字母小写的大小写混合法。
属性名不能与方法名相同。
privatecustomerName;
privateorderNumber;
privatesmpSession;
R5常量名使用全大写的英文描述,英文单词之间用下划线分隔开,并且使用staticfinal修饰。
publicstaticfinalintMAX_VALUE=1000;
publicstaticfinalStringDEFAULT_START_DATE="
2001-12-08"
;
S1包名采用域后缀倒置的加上自定义的包名,采用小写字母,都应该以com.botech开头(不包括一些特殊原因)。
除特殊原因包结构都必须以com.botech开头。
com.botech.产品名.模块名称
证据系统融合pgis包名com.botech.proof.pgis
S2通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结构,使代码成为自注释的。
清晰准确的函数、变量等的命名,可增加代码可读性,并减少不必要的注释。
S3常用组件类的命名以组件名加上组件类型名结尾。
Application类型的,命名以App结尾——MainApp
Frame类型的,命名以Frame结尾——TopoFrame
Panel类型的,建议命名以Panel结尾——CreateCircuitPanel
Bean类型的,建议命名以Bean结尾——DataAccessBean
EJB类型的,建议命名以EJB结尾——DBProxyEJB
Applet类型的,建议命名以Applet结尾——PictureShowApplet
S4如果函数名超过15个字母,可采用以去掉元音字母的方法或者以行业内约定俗成的缩写方式缩写函数名。
getCustomerInformation()改为getCustomerInfo()
S5准确地确定成员函数的存取控制符号:
只是该类内部调用的函数使用private属性,继承类可以使用的使用protected属性,同包类可以调用的使用默认属性(不加属性控制符号),对外公开的函数使用public属性。
protectedvoidgetUserName(){
。
。
privatevoidcalculateRate(){
S6含有集合意义的属性命名,尽量包含其复数的意义。
customers,orderItems
3.6编码
R1对于switch语句下的case语句,必须在每个case分支结束前加上break语句。
break才能真正表示该switch执行结束,不然可能会进入该case以后的分支。
至于语法上合法的场景“一个case后进入下一个case处理”,应该在编码设计上就避免。
R1数据库操作、IO操作等需要使用结束close()的对象必须在try-catch-finally的finally中close(),如果有多个IO对象需要close(),需要分别对每个对象的close()方法进行try-catch,防止一个IO对象关闭失败其他IO对象都未关闭。
try{
//......
}catch(IOExceptionioe){
//......
}finally{
try{
out.close();
}catch(IOExceptionioe){
in.close();
R2系统非正常运行产生的异常捕获后,如果不对该异常进行处理,则应该记录日志。
此规则指通常的系统非正常运行产生的异常,不包括一些基于异常的设计。
若有特殊原因必须用注释加以说明。
Try{
//.......
}catch(IOExceptionioe){
logger.error(ioe);
【注】不只是出异常了需要打印日志,对于重要的业务,在操作前和操作后都需要记录日志:
LOGGER.info()
R3自己抛出的异常必须要填写详细的描述信息。
便于问题定位。
thrownewIOException("
Writingdataerror!
Data:
"
+data.toString());
R4运行时异常使用RuntimeException的子类来表示,不用在可能抛出异常的方法声明上加throws子句。
非运行期异常是从Exception继承而来的,必须在方法声明上加throws子句。
非运行期异常是由外界运行环境决定异常抛出条件的异常,例如文件操作,可能受权限、磁盘空间大小的影响而失败,这种异常是程序本身无法避免的,需要调用者明确考虑该异常出现时该如何处理方法,因此非运行期异常必须有throws子句标出,不标出或者调用者不捕获该类型异常都会导致编译失败,从而防止程序员本身疏忽。
运行期异常是程序在运行过程中本身考虑不周导致的异常,例如传入错误的参数等。
抛出运行期异常的目的是防止异常扩散,导致定位困难。
因此在做异常体系设计时要根据错误的性质合理选择自定义异常的继承关系。
还有一种异常是Error继承而来的,这种异常由虚拟机自己维护,表示发生了致命错误,程序无法继续运行例如内存不足。
我们自己的程序不应该捕获这种异常,并且也不应该创建该种类型的异常。
R5在程序中使用异常处理还是使用错误返回码处理,根据是否有利于程序结构来确定,并且异常和错误码不应该混合使用,推荐使用异常。
一个系统或者模块应该统一规划异常类型和返回码的含义。
但是不能用异常来做一般流程处理的方式,不要过多地使用异常,异常的处理效率比条件分支低,而且异常的跳转流程难以预测。
注意:
Java5.0程序内部的错误码可以使用枚举来表示。
R6注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。
防止阅读程序时产生误解,防止因默认的优先级与设计思想不符而导致程序出错。
下列语句中的表达式
word=(high<
<
8)|low
(1)
if((a|b)&
&
(a&
c))
(2)
if((a|b)<
(c&
d))(3)
如果书写为
high<
8|low
a|b&
a&
c
a|b<
c&
d
(1)
(2)虽然不会出错,但语句不易理解;
(3)造成了判断条件出错。
R7避免使用不易理解的数字,用有意义的标识来替代。
涉及物理状态或者含有物理意义的常量,不应直接使用数字,必须用有意义的静态变量或者枚举来代替。
如下的程序可读性差。
if(state==0){
state=1;
...//programcode
应改为如下形式:
privatefinalstaticintTRUNK_IDLE=0;
privatefinalstaticintTRUNK_BUSY=1;
privatefinalstaticintTRUNK_UNKNOWN=-1;
if(state==TRUNK_IDLE){
state=TRUNK_BUSY;
Java5.0下建议使用枚举来表示。
异常:
publicvoidfunction(){
...
thrownewRuntimeException(“。
”);
R8数组声明的时候使用int[]index,而不要使用intindex[]。
使用intindex[]格式使程序的可读性较差,int[]index表示声明了一个int数组(int[])叫做index
如下程序可读性差:
publicintgetIndex()[]{
....
如下程序可读性好:
publicint[]getIndex(){
R9不要使用System.out与System.err进行控制台打印,应该使用工具类(如:
日志工具)进行统一记录或者打印。
代码发布的时候可以统一关闭控制台打印,代码调试的时候又可以打开控制台打印,方便调试。
R10集合必须指定模板类型
方便程序阅读,除去强制转换代码
Map<
String,MyObject>
map=newHashMap<
();
R11不要写没有必要的向上强制转型。
没必要写的向上强制转型会浪费性能,增加代码阅读难度
以下错误:
FileInputStreamfis=newFileInputStream(f);
InputStreamis=(InputStream)fis;
S1记录异常不要保存exception.getMessage(),而要记录exception.toString(),一般可通过日志工具记录完整的异常堆栈信息。
NullPointException抛出时常常描述为空