1、JAVA 编程规范 1. 命名规范定义这个规范的目的是让项目中所有的文档都看起来像一个人写的,增加可读性,减少项目组中因为换人而带来的损失。 (这些规范并不是一定要绝对遵守,但是一定要让程序有良好的可读性)1.1.基本规则较短的单词可通过去掉“元音”形成缩写; 较长的单词可取单词的头几发符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。1.2.具体规则 Package 的命名:应该都是由一个小写单词组成。如: package com.neu.util Class 的命名:必须由大写字母开头而其他字母都小写的单词组成,对于所有标识符,其中包含的所有单词都应紧靠在一起,而且大写中间单词
2、的首字母。如: public class ThisAClassName Class 变量的命名:必须用一个小写字母开头。后面的单词用大写字母开头。如:userName , thisAClassMethod Static Final 变量的命名: 应该都大写,并且指出完整含义。如:/*DBConfig PATH*/public static final String DB_CONFIG_FILE_PATH =“com.neu.etrain.dbconfig“; 参数的命名:和变量的命名规范一致。 数组的命名:应该总是用下面的方式来命名: byte buffer;而不是:byte buffer;
3、方法的参数:使用有意义的参数命名,如果可能的话,使用和要赋值的字段一样的名字: SetCounter(int size)this.size = size;2. 变量定义规范 去掉没必要的公共变量。 构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问的公共变量,防止多个不同模块或函数都可以修改、创建同一公共变量的现象。 仔细定义并明确公共变量的含义、作用、取值范围及公共变量间的关系。 明确公共变量与操作此公共变量的函数或过程的关系,如访问、修改及创建等。 当向公共变量传递数据时,要十分小心,防止赋与不合理的值或越界等现象发生。 防止局部变量与公共变量同名。 仔细设计结构中元素的布局
4、与排列顺序,使结构容易理解、节省占用空间,并减少引起误用现象。 结构的设计要尽量考虑向前兼容和以后的版本升级,并为某些未来可能的应用保留余地(如预留一些空间等。 留心具体语言及编译器处理不同数据类型的原则及有关细节。 严禁使用未经初始化的变量。声明变量的同时对变量进行初始化。 编程时,要注意数据类型的强制转换。3. 代码编写格式 代码样式:代码应该用 unix 的格式,而不是 windows 的(比如:回车变成回车+换行) 文档化:必须用 javadoc 来为类生成文档。不仅因为它是标准,这也是被各种 java 编译器都认可的方法。使用 author 标记是不被推荐的,因为代码不应该是被个人拥
5、有的。 缩进:应该是每行 2 个空格. 不要在源文件中保存 Tab 字符. 在使用不同的源代码管理工具时 Tab 字符将因为用户设置的不同而扩展为不同的宽度. 如果你使用 UltrEdit 作为你的 Java 源代码编辑器的话,你可以通过如下操作来禁止保存 Tab 字符, 方法是通过 UltrEdit 中先设定 Tab 使用的长度室 2 个空格,然后用 Format|Tabs to Spaces 菜单将 Tab 转换为空格。 页宽:应该设置为 80 字符. 源代码一般不会超过这个宽度, 并导致无法完整显示, 但这一设置也可以灵活调整. 在任何情况下, 超长的语句应该在一个逗号或者一个操作符后折
6、行. 一条语句折行后, 应该比原来的语句再缩进 2 个字符. 对: 中的语句应该单独作为一行. 例如,下面的第 1 行是错误的,第 2 行是正确的: if (i0) i + ; / 错误, 和 在同一行 if (i0) i + ; / 正确, 单独作为一行 , 语句永远单独作为一行 . 语句应该缩进到与其相对应的 那一行相对齐的位置。 括号:左括号和后一个字符之间不应该出现空格, 同样, 右括号和前一个字符之间也不应该出现空格. 下面的例子说明括号和空格的错误及正确使用: CallProc( AParameter ); / 错误 CallProc(AParameter); / 正确 不要在语句
7、中使用无意义的括号. 括号只应该为达到某种目的而出现在源代码中。下面的例子说明错误和正确的用法: if (I) = 42) / 错误 - 括号毫无意义 if (I = 42) or (J = 42) then / 正确 - 的确需要括号 4. 注释规范 Java 的语法与 C+ 及为相似 / 注释一行 /* */ 注释若干行/* */ 注释若干行,并写入 javadoc 文档 注释要简单明了。String userName = null; /用户 边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。 在必要的地方注释,注释量要适中。注释的内容要清楚、明了,含义准确,防止注释二
8、义性。保持注释与其描述的代码相邻,即注释的就近原则。 对代码的注释应放在其上方相邻位置,不可放在下面。对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释应放在此域的右方;同一结构中不同域的注释要对齐。 变量、常量的注释应放在其上方相邻位置或右方。 全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明。 在每个源文件的头部要有必要的注释信息,包括:文件名;版本号;作者;生成日期;模块功能描述(如功能、主要算法、内部各部分之间的关系、该文件与其它文件关系等) ;主要函数或过程清单及本文件历史修改记录等。/* Copy Right
9、Information : Neusoft IIT* Project : eTrain* JDK version used : jdk1.3.1* Comments : config path* Version : 1.01* Modification history :2003.5.1* Sr Date Modified By Why project.save(fos, “IDE Project File“); . 除非输出流一出作用域就关闭,非引用计数的程序语言,比如JAVA,是不能自动完成变量的清场工作的。必须象下面一样写: FileOutputStream fos = new File
10、OutputStream(projectFile);project.save(fos, “IDE Project File“); fos.close(); Clone,下面是一种有用的方法:implements CloneablepublicObject clone()try ThisClass obj = (ThisClass)super.clone();obj.field1 = (int)field1.clone();obj.field2 = field2;return obj; catch(CloneNotSupportedException e) throw new InternalE
11、rror(“Unexpected CloneNotSUpportedException: “ + e.getMessage(); final 类:绝对不要因为性能的原因将类定义为 final 的(除非程序的框架要求) 。如果一个类还没有准备好被继承,最好在类文档中注明,而不要将她定义为 final 的。这是因为没有人可以保证会不会由于什么原因需要继承她。 访问类的成员变量:大部分的类成员变量应该定义为 protected 的来防止继承类使用他们。 要用“int packets“ ,而不是 “int packets“,后一种永远也不要用。 public void setPackets(int p
12、ackets) this.packets = packets; CounterSet(int size)this.size = size;7. 排版规范 关键词和操作符之间加适当的空格。 相对独立的程序块与块之间加空行 较长的语句、表达式等要分成多行书写。 划分出的新行要进行适应的缩进,使排版整齐,语句可读。 长表达式要在低优先级操作符处划分新行,操作符放在新行之首。 循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分。 若函数或过程中的参数较长,则要进行适当的划分。 不允许把多个短语句写在一行中,即一行只写一条语句。 函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩
13、进风格。 编写程序块时和 应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以及 if、for、do、while 、 switch、case 语句中的程序都要采用如上的缩进方式。8. Java 文件格式所有的 Java(*.java) 文件都必须遵守如下的样式规则: 版权信息:必须在 java 文件的开头,其他不需要出现在 javadoc 的信息也可以包含在这里。比如: /* Copyright ? 2000 Shanghai XXX Co. Ltd.* All right reserved.*/ Package/Imports: pack
14、age 行要在 import 行之前,import 中标准的包名要在本地的包名之前,而且按照字母顺序排列。如果 import 行中包含了同一个包中的不同子目录,则应该用 * 来处理。 package .stats;import java.io.*;import java.util.Observable;import hotlava.util.Application;这里 java.io.* 使用来代替 InputStream and OutputStream 的。 Class :类的注释,一般是用来解释类的。 /* A class representing a set of packet an
15、d byte counters* It is observable to allow it to be watched, but only* reports changes when the current set is complete*/ 接下来是类定义,包含了在不同的行的 extends 和 implements public class CounterSet extends Observable implements Cloneable Class Fields: 类的成员变量: /* Packet counters*/protected int packets; public 的成员
16、变量必须生成文档(JavaDoc) 。proceted、private 和 package 定义的成员变量如果名字含义明确的话,可以没有注释。 存取方法:类变量的存取的方法。它只是简单的用来将类的变量赋值获取值的话,可以简单的写在一行上 /* Get the counters* return an array containing the statistical data. This array has been* freshly allocated and can be modified by the caller.*/public int getPackets() return copyA
17、rray(packets, offset); public int getBytes() return copyArray(bytes, offset); public int getPackets() return packets; public void setPackets(int packets) this.packets = packets; 其它的方法不要写在一行上。 构造函数: 它应该用递增的方式写(比如:参数多的写在后面) ,访问类型 (“public“, “private“ 等.) 和 任何 “static“, “final“ 或 “synchronized“ 应该在一行中,
18、并且方法和参数另写一行,这样可以使方法和参数更易读。 public CounterSet(int size)this.size = size; 克隆方法: 如果这个类是可以被克隆的,那么下一步就是 clone 方法: public Object clone() try CounterSet obj = (CounterSet)super.clone();obj.packets = (int)packets.clone();obj.size = size;return obj;catch(CloneNotSupportedException e) throw new InternalError(
19、“Unexpected CloneNotSUpportedException: “ + e.getMessage(); 类方法,下面写类的方法: /* Set the packet counters* (such as when restoring from a database)*/protected finalvoid setArray(int r1, int r2, int r3, int r4)throws IllegalArgumentException/ Ensure the arrays are of equal size/if (r1.length != r2.length |
20、 r1.length != r3.length | r1.length != r4.length)throw new IllegalArgumentException(“Arrays must be of the same size“);System.arraycopy(r1, 0, r3, 0, r1.length);System.arraycopy(r2, 0, r4, 0, r1.length); toString 方法: 无论如何,每一个类都应该定义 toString 方法: public String toString() String retval = “CounterSet: “
21、;for (int i = 0; i data.length(); i+) retval += data.bytes.toString();retval += data.packets.toString();return retval; main 方法 :如果 main(String) 方法已经定义了, 那么它应该写在类的底部. 9. 可读性 避免使用不易理解的数字,用有意义的标识来替代。 不要使用难懂的技巧性很高的语句。 源程序中关系较为紧密的代码应尽可能相邻。10. 性能 在写代码的时候,从头至尾都应该考虑性能问题。这不是说时间都应该浪费在优化代码上,而是我们时刻应该提醒自己要注意代码的效
22、率。比如:如果没有时间来实现一个高效的算法,那么我们应该在文档中记录下来,以便在以后有空的时候再来实现它。不是所有的人都同意在写代码的时候应该优化性能这个观点的,他们认为性能优化的问题应该在项目的后期再去考虑,也就是在程序的轮廓已经实现了以后。 不必要的对象构造, 不要在循环中构造和释放对象。 使用 StringBuffer 对象在处理 String 的时候要尽量使用 StringBuffer 类,StringBuffer 类是构成 String 类的基础。String 类将 StringBuffer 类封装了起来, (以花费更多时间为代价)为开发人员提供了一个安全的接口。当我们在构造字符串的
23、时候,我们应该用 StringBuffer 来实现大部分的工作,当工作完成后将 StringBuffer 对象再转换为需要的 String 对象。比如:如果有一个字符串必须不断地在其后添加许多字符来完成构造,那么我们应该使用 StringBuffer 对象和她的 append() 方法。如果我们用 String 对象代替 StringBuffer 对象的话,会花费许多不必要的创建和释放对象的 CPU 时间。 避免太多的使用 synchronized 关键字 避免不必要的使用关键字 synchronized,应该在必要的时候再使用它,这是一个避免死锁的好方法。11. 可移植性 Borland J
24、bulider 不喜欢 synchronized 这个关键字,如果你的断点设在这些关键字的作用域内的话,调试的时候你会发现的断点会到处乱跳,让你不知所措。除非必须,尽量不要使用。 换行:如果需要换行的话,尽量用 println 来代替在字符串中使用“n“。 不要这样:System.out.print(“Hello,world!n“); 要这样:System.out.println(“Hello,world!“); 或者你构造一个带换行符的字符串,至少要象这样: String newline = System.getProperty(“line.separator“); System.out.p
25、rintln(“Hello world“ + newline); PrintStream: PrintStream 已经被不赞成( deprecated)使用,用 PrintWrite 来代替她。 12. 质量保证 在软件设计过程中构筑软件质量。代码质量保证优先原则 (1)正确性,指程序要实现设计要求的功能。 (2)稳定性、安全性,指程序稳定、可靠、安全。 (3)可测试性,指程序要具有良好的可测试性。 (4)规范/可读性,指程序书写风格、命名规则等要符合规范。(5)全局效率,指软件系统的整体效率。 (6)局部效率,指某个模块 /子模块/ 函数的本身效率。 (7)个人表达方式 /个人方便性,指个
26、人编程习惯。 只引用属于自己的存贮空间。 防止引用已经释放的内存空间。 过程/函数中分配的内存,在过程/函数退出之前要释放。 过程/函数中申请的(为打开文件而使用的)文件句柄,在过程/函数退出前要关闭。 防止内存操作越界。 时刻注意表达式是否会上溢、下溢。 认真处理程序所能遇到的各种出错情况。 系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用。 系统运行之初,要对加载到系统中的数据进行一致性检查。 严禁随意更改其它模块或系统的有关设置和配置。 不能随意改变与其它模块的接口。 充分了解系统的接口之后,再使用系统提供的功能。 要时刻注意易混淆的操作符。当编完程序后,应从头至尾检查一遍这些操作符。 不使用与硬件或操作系统关系很大的语句,而使用建议的标准语句。 建议:使用第三方提供的软件开发工具包或控件时,要注意以下几点: (1)充分了解应用接口、使用环境及使用时注意事项。 (2)不能过分相信其正确性。 (3)除非必要,不要使用不熟悉的第三方工具包与控件。