都是网上找的,但很不错,所以就借用了
第一部分 命名
1、包(Package)
包的名字应该能够说明包的用途,通常应是名词或名词短语。包的名字应该全部由小写字母构成,例如“container”;如果包的用途必须由两个或多个单 词才能描述清楚,可以直接将这些单词连接作为包名,例如“webcontainer”;如果连接后的包名太长,可以使用单词的缩写(缩写必须不会引起歧 义)或取每个单词的首字母,例如“websvr”或“ws”。
2、类(Class)
类的名字应该能够说明类的用途,通常应是名词或名词短语。类的名字由若干单词连接而成,每个单词的首字母应大写,其他字母小写。例如“Server”、 “WebServer”。如果某个词是一个缩写形式,则这个词应全部大写,例如“HTTPServer”、“URLBuilder”。
3、字段(field)
字段的名字应该能够说明该字段的用途,通常取名词或名词短语,也可能是形容词。字段的名字由若干单词连接构成,第一个单词应全部小写,其余单词的首字母大写,例如“color”、“backgroundColor”或“enabled”。
4、静态终态字段(static final field)
静态终态字段的名字应该能够说明该字段的用途,通常取名词或名词短语,也可能是限定性的形容词或副词。静态终态字段的名字如果只有一个单词,则该单词应全 部大写,例如“NAME”、“HORIZONTAL”;静态终态字段如果由若干单词描述,则其名字应由这些单词以下划线(_)连接构成,每个单词均大写, 例如“USER_NAME”、“SCROLLBARS_NEVER”。
5、局部变量(local variable)
对于作用域较大(变量的有效范围超过5行代码)的局部变量,其命名应遵循上述“字段”的命名规则;对于作用域较小(变量的有效范围不超过5行代码)的局部 变量,在不至于引起混淆并且不会降低代码可读性的前提下,可以取简单的名字,例如,可以使用“i”作为小循环的循环变量名。
6、参数(parameter)
参数是指方法参数列表中的形参。参数的命名应遵循上述“字段”的命名规则。如果参数的意义与类中字段的意义相同,应尽可能使二者名字相同,例如:
public void setSize(int size) {
this.size = size
}
7、方法(method)
所有的方法(构造函数除外)名都应能说明方法的用途,通常取动词或动词短语,也可能是名词或名词短语。方法名由若干单词连接而成,第一个单词应全部小写, 其余单词的首字母大写。例如“connect”、“paintBorder”、“hashCode”。对于以名词或名词短语命名的方法,建议改成动词或动 词短语形式,例如,尽量不要使用“color”这样的方法名,而是使用“getColor”。如果方法是用动词或动词短语来描述的,并且该方法是用来做判 断或比较,返回一个boolean型的返回值,那么方法名中的动词应取单数第三人称形式,例如“equals”、“hasNext”。
8、集合(Collection)
对于集合或数组类型的变量,其名称应尽量取复数形式,相应的存取方法中也应使用复数形式,例如:
List children;
Collection getAttributes();
另外,除了特殊情况所有命名最好不要使用中英文混合。
第二部分 代码风格
1、文件注释
每个Java源程序文件的开头都应加入该文件的javadoc注释,包含文件的作者、用途、时间、版本等信息,例如:
/**
- Name: SomeClass.java
- Created: 2006-10-15
- Author: SomeBody
*/
2、包和导入声明
文件注释之后,应留一个空行,在空行后加入包声明;包声明之后加入一个空行,空行后加入导入声明。例如:
package com.somecompany.somesystem;
import java.util.Collection;
import javax.swing.JFrame;
import com.somecompany.othersystem.;
导入的书写次序不会影响程序的执行,但是为了提高源代码的可读性,建议将“java”开头的类首先导入,其次导入“javax”开头的类,然后倒入第三方工具包中的类,例如“org.apache.xml.”,最后导入自己开发的其他类。
如果要导入同一包中的若干个类,在数目不超过5个的情况下,应分若干行分别导入这些类;如果数目超过5个,则应用“*”代替,只写一行导入。
3、换行和缩进
源代码中一行的长度不要超过80个字符。超出则应拆分或适当换行。
代码的缩进量应为4个字符,可以使用4个空格代替,也可以使用宽度为4个字符的制表符代替。为了使源代码在不同的环境下缩进量不会失真,建议不要使用制表符,而是使用空格进行缩进。
4、代码块
代码块是指用“{”和“}”包围的一段代码。代码块用于类的定义、方法的定义、循环的定义、条件分支的定义等情况。代码块中的“{”应置于上一行代码的行 末,并且与之前的代码之间用一个空格分隔;代码块中的内容则应在换行并缩进之后书写;代码块最后的“}”应单独占一行,并与代码块开始的“{”所处的行缩 进位置相同。例如:
for (…..) {
doSomeThing();
}
5、类和接口
每个类和接口的声明之前应加入类的javadoc注释。
类或接口的声明(包括“class”、“interface”、“extends”、“implements”等关键字)应尽量在一行中完成,如果超出一行需要换行,则应在“extends”或“implements”等关键字之前换行,换行后应缩进。
类或接口的定义应符合上述“代码块”的规则。
6、字段
每个public的字段声明之前必须加入javadoc注释;其他字段可以不要javadoc注释。
每个字段的声明应单独占一行,不建议用一行定义多个字段。例如,应写成:
int firstField;
int secondField;
int thirdField;
而不要写成:
int firstField, secondField, thirdField;
7、方法
方法的声明之前应加入javadoc注释。
对于方法的声明部分,方法名与其之后的“(”之间不应有空格分隔;“(”或“)”与参数列表中的形参声明之间不应有空格分隔;每个形参声明与其之后的“,”之间也不应有空格分隔;参数列表中的“,”与下一个形参声明之间应用一个空格分隔。
方法的定义部分则应遵循上述“代码块”的规则。
例如:
public void someMethod(int param1, int param2, int param3) {
……
}
方法调用时,方法名与其后的“(”之间不应有空格;实参列表的规则与方法声明时的形参列表规则类似,例如:
callSomeMethod(value1, value2, value3);
8、判断、循环、异常处理语句
判断、循环、异常处理语句是指if(else)、switch、for、while(do)、try(catch)等语句。
这些语句中会用到括号(“()”),与方法参数列表中的括号不同,这些语句中的括号是跟随在某个Java关键字之后的。关键字与其之后的“(”之间应由一 个空个分隔;“(” 或“)”与其中的内容之间不应有空格分隔;对于for语句而言,括号中的每个分号(“;”)前面不应有空格,后面则应有一个空格。例如:
if (a > b)
for (int i = 0; i < 10; i ++)
catch (Exception e)
这些语句后面如果跟简单语句,必须换行并缩进,例如:
if (a > b)
doSomeThing();
否则,后面跟随的内容应符合“代码块”的规则,例如:
while (a > b) {
a –;
b ++;
}
try(catch)语句的例子如下:
try {
doSomeThing();
}
catch (Exception e) {
handleException(e);
}
9、运算符
每个运算符与操作数之间都应有空格分隔,例如:
b = true
a > b && a < c
不能写成:
b=true
a>b&&a
10、数组
数组的定义应写成:
int[] indices;
而不要写成:
int indices[];
11、字体
编辑Java源代码的文本编辑器字体应该设定为等宽字体,例如“Curier”,不应使用非等宽字体,例如“Times New Roman”,因为使用非等宽字体不利于控制代码的缩进与对齐。
第三部分 程序编写
1、exit方法
System.exit()方法应该只在main方法中被调用,而不出现在程序的其他任何地方。最好的做法是在main方法中也不调用System.exit()方法,因为main方法结束,主线程自动退出。
2、异常处理
如果代码执行的过程中,捕获了一个异常,绝对不能简单地将这个异常“吃”掉或是打印一些类似于“1111111”的信息,而是应该谨慎对待——因为异常包含了程序执行过程中的原始错误信息,良好的异常处理策略可以为后期的调试、维护等工作带来极大的便利。
从功能的角度来看,代码中捕获的异常通常分为两种情况:可以预见的和不可预见的。不可预见的异常是指在代码编写期间没有考虑到或无法考虑到的异常情况,例 如进行数据库访问时连接突然中断。可以预见的异常是指代码编写期间就可以考虑到的“合理”异常,例如将字符串解析为数字时引发的 NumberFormatException。
异常的处理应该以方法为单位,也就是说,某个方法内部捕获到一个异常时,应该由该方法决定如何处理此异常。
对于可以预见的异常,可以采取两种处理策略:处理异常或抛出异常。处理异常是指该异常在当前方法的处理能力之内,该方法可以自行处理此异常。例如,用户输 入某个字符串后,要求程序自行解析,如果为数字,则视为用户的身份号码;如果不为数字,则视为用户的姓名。假定解析用户输入字符串的方法名为 parseInput,那么在parseInput方法执行的过程中,可能会引发NumberFormatException。这个异常对于 parseInput而言是可以预见的,并且是它可以自行处理的,那么它应该自己捕获此异常,而不必将其另行抛出。
假如在上面的例子中,用户姓名的合法性本身还有一套校验规则,那么在parseInput方法中处理了NumberFormatException之后, 执行用户姓名校验时还有可能引发异常。这个异常虽然也是可以预见的,但是已经超出了parseInput方法的职责范围,它应该将此异常继续抛出。抛出的 异常会被更外围的方法捕获,由它们最终决定如何处理该异常,例如提示用户或中止程序。
对于不可预见的异常,只有一种策略可以采用:继续抛出。
对于每个方法而言,处理异常的原则就是:在自己职责范围之内的异常,一定要自己处理,而不能抛出;在自己职责范围之外的异常,则一定要抛出,绝对不能自行处理(例如把它“吃掉”)。
应该选择“处理异常”还是“抛出异常”并没有严格的标准,往往要依靠经验并从实际的需求出发。但是通常而言,选择“处理异常”策略的方法都属于程序“较外 围”(即在调用堆栈中处于比较底层)的业务控制方法,因为只有它们知道业务需求,只有它们才能决定发生某个异常时应该通知用户、记入日志还是中止程序。对 于大多数工具方法或通用方法而言,它们并不了解实际的业务需求,在异常发生时,它们最好的选择就是“抛出异常”策略——将异常原封不动地抛给外围的业务控 制方法,由它们作出决定。
3、状态判断
在可能的情况下,应该尽量使用异常而不是返回值来表示某个方法的执行状态。某个方法可以在任何需要的时候抛出异常,而不仅仅是在发生错误的时候。例如,一个校验用户身份的方法如下:
boolean authenticate(String user, String password);
使用该方法校验用户身份只能返回“true”或“false”,表示用户校验通过与否,对于校验不通过的情况,该方法无法返回更多的信息。如果将该方法设计成如下的样子:
void authenticate(String user, String password) throws Exception;
调用该方法时,如果没有引发异常,表示用户校验通过;如果发生异常,则表示校验未通过。根据抛出的异常,还可以进一步得到校验未通过的原因,并且可以将异常的详细信息反馈给用户或记入日志。这样的设计不但可以带来更好的用户体验,而且极大地方便了以后程序的调试和维护。
一个异常包含的信息远远比一个简单的返回值丰富的多。
4、垃圾回收
不要迷信垃圾回收。
由于finalize方法的调用不是可靠的,并且调用的时间是不可预知的,因此不要依赖垃圾回收机制使用finalize方法来做清理工作。
例如,如果使用了java.sql.Connection对象,即使不调用它的close方法,系统也会在垃圾回收时清理它所使用的资源。但是这种方法并 不可取,尤其是对频繁使用数据库连接的程序而言——因为很有可能在系统执行垃圾回收之前,已经堆积了大量无用的Connection对象,占用了大量的系 统资源,影响系统的执行效率。最好的方法还是在一个Connection对象使用完毕后马上调用它的close方法显式释放资源。
除此之外,除非你编写的是非常基础的服务程序,否则不要轻易调用System.gc()或Runtime.gc()方法,因为垃圾回收的过程本身会占用系统资源,垃圾回收的过程调用不当的话,非但不会提高系统效率,反倒会影响系统的运行。
5、终态类(final class)
不要为了提高系统的性能而设计任何终态类(当然,有特殊需求的情况除外)。很可能在未来的某个时候被设计为终态的类需要被派生。
6、工具类
工具类用来提供一组通用的公共方法。
工具类应该设计成为拥有一组静态的工具方法,因而不需要实例化就可以使用;
工具类可以有一组静态终态(static final)字段表示通用常量,但是不应有任何非静态字段;
工具类应该声明一个私有的缺省构造函数,以防止被继承或被实例化。
7、System.out和System.err
不要滥用System.out和System.err。
在编写程序、单元测试和后期调试的时候,很多人喜欢直接或间接地使用System.out和System.err打印调试信息 (Throwable.printStackTrace也间接使用了System.err)。当程序最终发布的时候,如果忘了删除这些调试信息,会造成很 多“垃圾”输出,严重的时候,这些“垃圾”输出会导致日志文件迅速挤满硬盘。
建议使用java.util.logging或其他一些第三方的工具包来打印调试信息,而不要直接使用System.out或System.err。当 然,也可以自行编写一个简单的Debug工具类实现调试信息的输出。这样,当程序发布时,只需要进行简单的修改或配置,就可以除去所有的调试信息。
8、静态方法
静态方法一定要静态调用,而不要使用实例。例如,要挂起当前线程,应该调用“Thread.sleep(1000);”而不是“Thread.currentThread().sleep(1000);”。
9、StringBuffer
在对字符串进行较多的拼接、拆分工作时,应尽量使用StringBuffer对象,而不是直接对String对象操作。
10、代码复用
千万不要使用过多的“复制、粘贴”实现代码的复用。如果一段代码被复制、粘贴了超过3次,就应该考虑将这段代码重新封装到一个方法中。如果出现第4个地方需要使用这段代码,并且需要对代码作稍许改动,则应该考虑将刚才封装的方法进行改造而不是重新定义一个方法。
不要认为使用复制、粘贴会比重新封装一个方法节省时间。因为在将来项目进行到某一阶段的时候,这段代码可能被复制了200份,并且改动了300处,这个时 候如果这段代码的逻辑发生变化——哪怕是微小的变化,无论是重新找到并修改这200处地方,还是回头重新将他们封装为一个方法,工作量都将是惊人的。