(1)
(2)虽然不会出错,但语句不易理解;(3)造成了判断条件出错。
6、避免使用不易理解的数字,用有意义的标识来替代。
涉及物理状态或者含有物理意义的常量,不应直接使用数字,必须用有意义的静态变量或者枚举来代替。
示例:
如下的程序可读性差。
if(state==0)
{
state=1;
... //programcode
}
应改为如下形式:
privatefinalstaticintTRUNK_IDLE=0;
privatefinalstaticintTRUNK_BUSY=1;
privatefinalstaticintTRUNK_UNKNOWN=-1;
if(state==TRUNK_IDLE)
{
state=TRUNK_BUSY;
... //programcode
}
注意:
JDK1.5下建议使用枚举来表示。
7(删除)、数组声明的时候使用 int[] index ,而不要使用 int index[]
说明:
使用int index[] 格式使程序的可读性较差,int [] index 表示声明了一个int数组(int [])叫做index
示例:
如下程序可读性差:
publicintgetIndex()[]
{
....
}
如下程序可读性好:
publicint[]getIndex()
{
....
}
8、不要使用 System.out 与 System.err 进行控制台打印,应该使用工具类(如:
日志工具)进行统一记录或者打印。
说明:
代码发布的时候可以统一关闭控制台打印,代码调试的时候又可以打开控制台打印,方便调试。
9、集合必须指定模板类型
说明:
方便程序阅读,除去强制转换代码
示例:
Mapmap=newHashMap();
10、一个文件不要定义两个类(并非指内部类)。
说明:
方便程序的阅读与代码的维护
注意:
一个文件定义两个类,在play框架的生产模式会报错,因为play重写了class的加载方法,生产模式启动时进行预编译,这时会保存;但是在开发模式则不会报错,因为开发模式不会进行预编写,而是在运行时编译,jvm运行时编译则不会出错。
11(抽取成一个日志公用类)、对Debug,Info级别日志输出前必须对当前的调试等级先进行判断。
说明:
日志一般都会有不少字符串的处理,如果不是Debug级别就没有必要进行处理
示例:
if(logger.debugEnable())
{
logger.debug(“request:
”+request.getMethod());
}
12、不要使用循环将集合转为数组,可以使用集合的toArray()方法。
说明:
更好的性能,代码更加简洁
(1、数据量多的情况下,ArrayList跟LinkedList是否应该区分循环访问方式,即(for跟foreach)的区别;
(2、当需要使用Map进行拼接数据的时候,HashMap跟LinkedHashMap使用循环打印出来的数据顺序跟添加的顺序是不一样的,是否也需要区分开;
示例:
ArrayListlist=newArrayList();
list.add....
String[]array=newString[list.size()];
list.toArray(array);
13、JDK1.4中大量字符串的“相加”操作应该使用StringBuffer。
JDK1.5以上版本大量字符串“相加等于”操作如果不涉及线程安全应该使用StringBuilder,如果有线程安全的要求应该使用StringBuffer
说明:
大量的String相加等于处理性能消耗较多。
“大量”一般指5次“+=”以上或者在循环中进行字符串+=操作。
StringBuilder的性能优于StringBuffer,但是是非线程安全的。
示例:
不推荐:
Stringstr=“”;
str+=”a”;
str+=”b”;
str+=”c”;
str+=”d”;
str+=”e”;
推荐:
StringBuildersb=newStringBuilder();
sb.append(“aa”);
sb.append(“bb”);
sb.append(“cc”);
JDK1.4使用StringBuffer。
JDK1.5如果不涉及线程安全用StringBuilder替代以上示例。
14、对类中日志工具对象logger应声明为static.
说明:
防止重复new出logger对象(logger指各种日志工具类,可以是log4j,jdklogger,内部API等,尽管一些logger对LogFactory工厂有一些优化,但是我们也必须防止代码没有必要的运行)。
15、不能用“==”比较两个字符串(Long对象等)内容相等,能用基本类型就是基本类型
说明:
两个字符串在比较内容是否相等的时候,如果使用“==”,当两个字符串不是指向内存中同一地址,那么即使这两个字符串内容一样,但是用“==”比较出来的结果也是false。
所以两个字符串在比较内容是否相等的时候一定要使用“equals”方法。
示例:
publicclassTest{
publicstaticvoidmain(String[]args)
{
Stringa=newString("a");
Stringa2="a";
if(a==a2)
{
System.out.println("a==a2returntrue.");
}
else
{
System.out.println("a==a2returnfalse.");
}
if(a.equals(a2))
{
System.out.println("a.equals(a2)returntrue.");
}
else
{
System.out.println("a.equals(a2)returnfalse.");
}
}
}
最终输出的结果为:
a==a2returnfalse.
a.equals(a2)returntrue.
16、对list做foreach循环时,循环代码中不能修改list的结构
说明:
在jdk1.5版以上的foreach循环写法中,不能在循环代码中对正在循环的list的结构进行修改,即对list做add、remove等操作,如果做了这些操作,必须立即退出循环,否则会抛出异常。
17、避免空指针异常,增加静态代码检查
说明:
空指针异常是编码过程中最常见的异常,在使用一个对象的时候,如果对象可能为空,并且使用次对象可能会造成空指针异常,那么需要先判断对象是否为空,再使用这个对象。
18、避免下标越界,增加静态代码检查
说明:
访问数组、List等容器内的元素时,必须首先检查下标是否越界,杜绝下标越界异常的发生。
19、将字符串转数字时没有捕获NumberFormatException异常,写工具类
说明:
调用Java方法将字符串转换为数字时,如果字符串的格式非法,会抛出运行时异常NumberFormatException。
示例:
错误例子:
publicIntegergetInteger1(Stringnumber)
{
//如果number格式非法,会抛出NumberFormatException
returnInteger.valueOf(number);
}
正确的处理方法如下:
publicIntegergetInteger2(Stringnumber)
{
try
{
returnInteger.valueOf(number);
}
catch(NumberFormatExceptione)
{
...
//记录日志异常信息
returnnull;
}
}
注意:
在捕获异常后一定要记录日志。
20、循环体编码时不考虑性能,循环体中包含不需要的重复逻辑。
(考虑循环体的性能)
说明:
循环体是软件中最容易造成性能问题的地方,所以在进行循环体编码时务必考虑性能问题。
在循环体内重复使用且不会变化的资源(如变量、文件对象、数据库连接等),应该在循环体开始前构造并初始化,避免在循环体内重复和构造初始化造成CPU资源的浪费。
除非业务场景需要,避免在循环体内构造try...catch块,因为每次进入、退出try...catch块都会消耗一定的CPU资源,将try...catch块放在循环体之外可以节省大量的执行时间。
21、equals操作时没有将常量放在equals操作符的左边,增加静态代码检查
说明:
字符串变量与常量比较时,先写常量,这样可以避免空指针异常。
示例:
publicstaticfinalStringSP_NAME="SPNAME";
publicvoidequalsConst()
{
Stringtemp=null;
//错误;//在temp为null的情况下,此时会导致意想不到的异常抛出,如果将常量放在左边,就不会有这种问题。
if(temp.equals(SP_NAME))
{
temp=SP_NAME+"AA";
}
}
21命名规范
12.1类名、变量名(非final)、方法名
12.2驼峰式命名
12.3不能使用没有任何含义的英文字母进行命名
12.4不能使用拼音进行命名,统一使用准确的英文进行命名
不采用简写方式命名(除公认的常用简写)
12.5包名
以cn.pp.ppbase.项目名.xxx 命名,都采用小写,连续的单词只是简单地连接起来,不使用下划线。
12.6接口与类的命名
接口不要以 I 开头。
如:
IUserService,而直接采用具体的命名方式如UserService
12.7抽象类命名
抽象类命名使用:
Abstract+名词的方式进行命名,如:
AbstractMessage。
12.8实现类命名
对于只有一个实现类的情况,通常先不采用接口方式,直接采用实现类即可,如果有多个实现类,则采用名称+抽象名称,如UserMessage、AdminMessage。
注意:
项目中的Service层,目前大多只有一个实现,所以不采用接口方式,直接使用具体类即可。
12.9工具类命名
统一使用:
名词+Util进行命名,如:
UrlUtil、StringUtil……
12.10变量命名
所有变量(描述状态的除外)统一以准确的名词性英文命名,名词性英文语法如下:
普通名词,如:
user、clubMember、order等
组合名词,即名词+名词,如:
clubMemberServiceOrder,paymentResult等
带修饰语(定语)名词,如:
checkingResult,messageSendingTask(主动,用ing),closedOrder(已经关闭的订单,用ed)
描述状态的变量统一以准确的形容词性英文命名,形容词性英文语法如下:
普通形容词,如:
active,inactive,valid,invalid等
动词转形容词,表示状态,如:
close > closed,stop > stopped等
动词转形容词,标示能动,如:
delete > deletable,use > useful等
对于反映状态的变量,不要在命名前面加“is”,因为自动生成的get方法,对于boolean值,方面名自动会变为is***
常量用全大写,单词之间用“_”分割,如:
public static final String QUERYCLUBMEMBER_HQL=”…”;
对于成员变量,其名称可省略所属类的名称,如:
public class User {
private String clubMemberName; //NOT GOOD
private String name; //GOOD
}
12.115、方法命名
方法名命名规则:
动词:
init,validate,pay等
动词+介词+(宾语):
compareTo,getById等
动宾短语(表示动作):
createUser,publishPrivilege
谓表短语(表示状态):
isClosed,isUserExisted,canUserBeDeleted等
单复数的使用,对于一些动作需要操作多个对象,方法名要通过名词复数反映出来,例如:
deleteOrders(删除订单,可能多个)
如果一个方法设计两个动作或对象,用“And”连接,如:
createProductAndTag,但一般情况下,不推荐一个方法做多于一件事情
如非必要,或常见的简写,尽量不要使用简写,因为简写很难阅读,容易误解,宁愿方法名稍微长一些,也要让方法名用正确的短语来表述,由于一个方法一般不建议做多于一件事情,所以方法名一般不会太长。
一些Java业界约定俗成的方法命名:
与…进行比较:
compareTo
获取单例对象:
getInstance
是否相等:
equals
初始化:
init
12.12系统的命名约定
12.12.1接口、类的命名约定
类名
示例
Struts Action类
***Action OrderAction
Struts Interceptor类
***Interceptor AuthenticationInterceptor
系统监控器类
***Monitor MemcachedMonitor
逻辑层类
***Service UserService
VO/DTO(视图对象)
实体名+VO UserVO
Entity(领域对象)
实体名 User
DAO层
***Dao UserDao
12.12.2常规方法的命名约定
方法名
示例
创建
create*** create createUser
更新
update*** update updateUser
删除
delete*** delete deleteOrder
批量删除
delete***(复数) deleteOrders
获取单个对象
get*** get getUser
获取单个对象根据某个参数
getBy*** getMarketingActivityByCode
批量获取多个对象
batchGet***
列表(不分页)
list***(复数) listOrders
列表(分页)
paged***(复数) pagedOrders
激活/启用
activate*** activeMarketingActivity
停用
inactivate/stop*** inactivateMarketingActivity
如果类名已经包含一些名称,方法和操作可以不写响应的名称,例如UserDao 的方法get 而不用getUser