1、Java编码规范526Java 编码规范1. 概述本标准系公司首次发布实施,主要针对公司所有软件产品源代码范围的Java编码风格,对Java文件的文件组织、代码风格、注释、命名、声明、异常、习惯等方面均做规范,以保障公司项目代码的易维护性和编码安全性。1.1. 术语 Pascal case - 所有单词第一个字母大写,其它字母小写。例如:Person, OrderDetail, OilTank。 Camel case - 除了第一个单词,所有单词第一个字母大写,其他字母小写。例如:oilLevel, customerName。在后面的描述中我们使用 Pascal 代表第一种表示方式, Came
2、l代表第二种表示方式。2. 重要规范2.1. 操作规范2.1.1. 模板及格式化 开发人员必须保证代码格式化的一致性,否则可能会导致代码冲突。轻微的冲突耗费人力合并代码;严重时可能导致代码丢失,引起bug或者故障。 开发人员必须配置cdrundle的codetemplates.xml代码模板文件。 开发人员必须配置cdrundle的cdrundleFormatter.xml代码格式化文件。 每次提交代码之前,必须对java代码format。 模板文件:Eclipse中配置的位置: Window-Preferences-Java-Code templates Window-Preferences
3、-Java-Formatter2.1.2. 代码提交 为防止冲突,任何时候,代码(及配置文件)提交前,先从SVN中更新代码和配置文件,以及早发现不兼容的代码变更和冲突。提交代码(及配置文件)时,如果发生冲突时,先看历史说明,再找相关人员确认,坚决不允许强制覆盖。每次提交代码之前,必须检查是否有eclipse warning,并修复所有的warning。开发过程中定期使用FindBugs扫描代码,合并代码时不允许出现高等级问题。2.1.3. 垃圾清理 对从来没有用到的或者被注释的方法、变量、类、配置文件,动态配置属性等要坚决从系统中清理出去,避免造成过多垃圾。2.2. 日志规范2.2.1. 日志
4、输出 生产代码禁止以System及Throwable.printStackTrace的方式输出日志信息,必须用Logger替代。 对trace/debug/info级别的日志输出,必须使用条件输出形式,否则大量的日志会增加来自对象toString的性能成本。 对于日志的打印,任何情况下都不允许日志错误导致业务失败。2.2.2. 错误日志 对于由于系统原因造成业务处理失败的事件,需要记录错误日志。非系统原因的业务处理失败,不应该记录错误日志(推荐使用warn级别),避免错误日志过大,影响紧急情况下的故障分析不诊断。2.3. 注释规范 对于一个完整的类,应该包括Cdrundle的版权注释、类的说明
5、注释、类成员变量注释,以及public、protected、private方法的注释(setter、getter、接口的实现方法除外)。 必须保证代码和注释的一致性。 正确区分使用文档注释和实现逻辑注释。2.4. 异常处理 捕捉到的异常,不允许不做任何处理就截断,至少要记入日志,或重新抛出。 最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。2.5. 安全规范2.5.1. WEB安全 对于前台的web页面,必须加上表单防重复提交功能;对于业务关键字段需要加上防篡改的功能,否则可能造成业务重复执行或者被客户端恶意修改。 对于前台的web页面,严禁出现方便调试的后门页面。 不允许出现
6、页面向自身重定向、或者多个页面间相互重定向的情况。如果控制不当,很容易造成系统宕机。2.5.2. 敏感信息的保护用户的敏感信息包括密码、短信验证码、支付验证码、身份证号、银行卡号、银行密钥,商户密钥等信息,用户敏感信息不能泄露,否则可能会带来不安全因素。可能会导致敏感信息泄露的方式有:Logger、URL的get参数(因为URL的get参数会在apache日志中被输出)。2.6. 通用规范2.6.1. 配置信息的使用 避免将UserID、URL、文件名、系统开关参数、业务规则的可变参数等硬编码。 2.6.2. 资源的使用对系统资源的访问,使用后必须释放系统资源。这类资源包括:文件流、线程、网络
7、连接、数据库连接等。 对于文件、流的IO操作,必须通过finally关闭。 对于线程,线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。 对于网络连接与数据库连接,必须由框架通过连接池提供,不允许应用中自行建立网络与数据库连接。3. 类的编写规范 所有包、类、接口、方法、属性、变量、参数均使用英文单词进行命名。 命名包、类、接口、方法以及变量时,尽量使用贴近问题域的且意义丰富的名称。 修改源代码时,应尽量保持与所修改系统的编码风格保持一致。 所有包名必须使用pany前缀,所有项目使用pany.project name,company 是公司简称,project name 是项目的缩写
8、。 注意尽量不要用生僻的缩写,尤其是中文缩写。4. 格式规范 包的导入应该按照相关性进行分组。import java.io.IOException;import .URL;import java.rmi.RmiServer;import java.rmi.server.Server;import javax.swing.JPanel;import javax.swing.event.ActionEvent;import org.linux.apache.server.SoapServer; 只倒入明确需要的类,这样只要看导入列表,就可以知道该类依赖于哪些类和接口,保证可读性。import ja
9、va.util.List; / 避免: import java.util.*import java.util.Arraylist;import java.util.HashSet; 类和接口中元素的布局顺序。1、类和接口的文档描述2、类和接口的声明3、类的静态变量,按照public,protected,package,private的顺序。4、实例变量,按照public,protected,package,private的顺序。5、类的方法,无固定顺序。 类的声明,基类和实现的接口应该独立成行,保证可读性。class UserManagerImplextends AbstractManager
10、implements IUserManager 方法修饰关键字定义顺序。 static abstract synchronized unuaual final native methodName注意访问标示符一定要在最前面。public static double square(double a);/避免: static public double square(double a); 变量声明,采用 Camel 表示法不要在一行声明多个变量。/推荐int level;int size;/避免int level, size; 保证明确的类型转换,不要默认进行隐式类型转换intValue = (i
11、nt) floadValue; /避免 intValue = floatValue 数组指示符紧跟类型变量int a = new int20; / 避免: int a = new int20一个变量要代表独立的意思,不要在其生命周期赋予它不同的概念。int tempValue;tempValue = maxValue;tempValue = minValue;tempValue = anotherValue;tempValue 在生命周期内表示了各种各样的意图,增加理解代码的难度。 应该为每个独立概念定义单独的变量:int tempMaxValue;int tempMinValue;int t
12、empAnotherValue; 仅仅循环控制变量才能出现在 for()循环中sum = 0;for (i = 0; i 100; i+) sum += valuei;/避免:for (i = 0, sum = 0; i 100; i+)sum += valuei; 循环变量应靠近循环体初始化 isDone = false while(!isDone)/避免isDone = false;while(!isDone) 避免长的布尔表达式,应换成多个更容易理解的表达式。bool isFinished = (elementNo maxElement);bool isRepeatedEntry = e
13、lementNo = lastElement;if (isFinished | isRepeatedEntry) / 避免if (elementNo maxElement)| elementNo = lastElement) 不要在条件语句中执行方法,以提高可读性InputStream stream = File.open(fileName, w);if (stream != null) /避免if (File.open(fileName, w) != null) 代码缩进,应该使用 4 个空格为一个单位进行缩进。public String invoke() throws Exception
14、.String profileKey = invoke: ;try .UtilTimerStack.push(profileKey);if (executed) .test = true;catch 条件语句的主要形式,即使单条语句,也要使用括号括起来。if (condition) statements;if (condition) statements; else statements;if (condition) statements; else if (condition) statements; else statements; 空循环体也要使用完整的块for (initializat
15、ion; condition; update) ; switch 语句的使用格式switch (condition) case ABC :statements;/穿透,一定要做出注释case DEF :statements;break;case XYZ : statements; break;default : statements; break; try-catch 使用格式try statements;catch (Exception exception) statements;try statements;catch (Exception exception) statements;fi
16、nally statements; 空格的使用1、运算符两边应该各有一个空格。2、Java 保留字后面应跟随一个空格。3、逗号后面应跟随一个空格。4、冒号两个应各有一个空格。5、分号后面应跟随一个空格。a = (b + c) * d; / NOT: a=(b+c)*dwhile (true) / NOT: while(true). doSomething(a, b, c, d); / NOT: doSomething(a,b,c,d); case 100 : / NOT: case 100:for (i = 0; i 10; i+) / NOT: for(i=0;i10;i+) . 逻辑上紧密
17、相关的代码块应该用一个空行分开。/ Create a new identity matrixMatrix4x4 matrix = new Matrix4x4();/ Precompute angles for efficiencydouble cosAngle = Math.cos(angle); double sinAngle = Math.sin(angle);/Specify matrix as a rotation transformationmatrix.setElement(1, 1, cosAngle); matrix.setElement(1, 2, sinAngle); ma
18、trix.setElement(2, 1, -sinAngle); matrix.setElement(2, 2, cosAngle);/ Apply rotationtransformation.multiply(matrix); 为了保证可读性,变量名应该左对齐。TextFile file;int nPoints;double x, y;/避免TextFile file;int nPoints;double x, y; 像前面一般规则里说的那样,任何提高代码可读性的排版都可以去尝试, 下面是一些例子。if (a = lowValue) compueSomething();else if (
19、a = mediumValue) computeSomethingElse();else if (a = highValue) computeSomethingElseYet();value = (potential * oilDensity) / constant1 +(depth * waterDensity) / constant2 +(zCoordinateValue * gasDensity)/ constant3;minPosition = computeDistance(min, x, y, z);averagePosition = computeDistance(average
20、, x, y, z);switch (phase) case PHASE_OIL : text = Oil; break; case PHASE_WATER : text = Water; break; case PHASE_GAS : text = Gas; break; 当对 if 语句中的条件进行折行时,应该使折行的条件语句相对主功能语句再行缩进 4 个空格,以突出主要功能语句。/使用这种缩进,突出主要功能语句。if (condition1 & condition2)| (condition3 & condition4)|!(condition5 & condition6) doSome
21、thingAboutIt();/避免使用这种缩进,主功能语句不突出。 if (condition1 & condition2)| (condition3 & condition4)|!(condition5 & condition6) doSomethingAboutIt(); 三元条件运算符 可以使用如下三种表达方式,条件要用括号括起来。alpha = (aLongBooleanExpression) ? beta : gamma;alpha = (aLongBooleanExpression) ? beta: gamma;alpha = (aLongBooleanExpression)?
22、beta: gamma5. 命名规范5.1. 一般命名规范 包名应该用小写字母,不要出现下划线等符号,名词用有意义的缩写或 者英文单词。示例:/推荐 com.cdrundle.normativefile.daojava.lang.util/避免com.Esse-tech.buSiness 所有类命名使用 Pascal 表示方式,使用名词组合。UserManager, ClassLoader, HttpHeaderResult 接口命名使用字母“I”加上 Pascal 形式的表示方式。IQuery, IDataAccess,IReportBuilder 使用名词组合或形容词去命名一个接口,接口声
23、明了一个对象能提供的 服务,也描述了一个对象的能力。一般以“able”和“ible”作为后缀, 代表了一种能力。public interface Runnablepublic void run();public interface Accessiblepublic Context getContext(); 变量名和参数名使用 Camel 表示方式。userName, objectFactory, entrys, list 对于常量名,使用大写字母,并使用下划线做间隔。 MAX_TIMES, DEFAULT_NAME 程序中应该使用常量代替“25”,“100”等实际的数字,如:/推荐if(ti
24、mes = MAX_TIMES)/避免if(times = 25)这样做的好处是,当因需要修改实际的数字时,比如修改 25 为 30,只需要 修改一处。 方法名应该使用动词开头,使用Camel表示方式,一般由动词+名词组成。getName, initialize, addParameter, deleteUser 缩写字母也应该保持首字母大写exportHtmlSource(); / 避免: exportHTMLSource();openDvdPlayer(); / 避免: openDVDPlayer(); 变量的名字应该和类型名称一致void setTopic(Topic topic) /
25、避免: void setTopic(Topic value)/ 避免: void setTopic(Topic aTopic)/ 避免: void setTopic(Topic t)void connect(Database database)/ 避免: void connect(Database db)/ 避免: void connect(Database oracleDB)当同时定义多个属于同一个类的变量时,把类型作为实例的后缀,如:Point startPoint; Point centerPoint;这样做是为了从实例名就可以推断它的类型名称。 根据变量的作用范围,作用范围大的应该使用
26、长名称,作用范围大,表明变量的生命周期比较长,为了有助于理解,应尽量用长名称以表达变量的真实意图。反之,对于作用范围小,可以使用一些简化的名称,比如 i,j,k 等,提高编程效率。for(int i =0;i times; i+)5.2. 特殊命名规范 使用 get/set 对类属性进行访问,这是 Java 社区的核心编码规范。 使用 is 前缀表示一个布尔变量和方法。isUsed, isEmpty,isVisible,isFinished有时也可以使用 has,can,should:boolean hasLicense();boolean canEvaluate();boolean shou
27、ldAbort = false; 在查询方法中应使用 find 作为前缀vertex.findNearestVertex();matrix.findSmallestElement();node.findShortestPath(Node destinationNode); 使用 initialize 作为对象初始化的方法前缀,也可以简写为init initializeFiles();init();initFontSet(); 对于对象集合,变量名称应使用复数。Collection points;int values; 对于抽象类,应该使用Abstract前缀。AbstractReportBui
28、lder,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
29、避免使用否定布尔变量bool isError; / 避免: isNoErrorbool isFound; / 避免: isNotFound 异常类应该使用 Exception 作为后缀。AccessException, RuntimeException 缺省接口实现应该使用 Default 前缀class DefaultTableCellRenderer implements TableCellRenderer 对于单例类(Singleton),应该使用 getInstance 方法得到单例。class UnitManager private final static UnitManager instance = new UnitManager();private UnitManager() .public static UnitManager getInstance()return instance; 对于工厂类,进行创建对象的方法,应该使用 n
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1