Java 开发规范
第1章 绪论
1.1目的
本规范的目的是使本组织能以标准的、规范的方式设计和编码。通过建立编码规范,以使每个开发人员养成良好的编码风格和习惯;并以此形成开发小组编码约定,提高程序的可靠性、可读性、可修改性、可维护性和一致性等,增进团队间的交流,并保证软件产品的质量。
1.2范围
本规范适用于本公司下所有软件项目、产品等的设计、开发以及维护、升级 等。本规范使用于本公司的所有软件开发人员,在整个软件开发过程中必须遵循此规范。
1.3概述
对于代码,首要要求是它必须正确,能够按照设计预定功能去运行;第二是要求代码必须清晰易懂,使自己和其他的程序员能够很容易地理解代码所执行的功能等。然而,在实际开发中,每个程序员所写的代码却经常自成一套,很少统一,导致理解困难,影响团队的开发效率及系统的质量等。因此,一份完整并被严格执行的开发规范是非常必须的,特别是对软件公司的开发团队而言。
最根本的原则:代码虽然是给机器运行的,但却是给人读的!
第2章 代码组织与风格
2.1基本原则
代码的组织和风格的基本原则是:便于自己的开发,易于与他人的交流。 因个人习惯和编辑器等可以设置和形成自己的风格,但必须前后一致,并符合本规范的基本要求和原则。
本章所涉及到的内容一般都可在 Java 集成编辑环境中进行相应设置。
2.2缩进
子功能块当在其父功能块后缩进。 当功能块过多而导致缩进过深时当将子功能块提取出来作为子函数。
代码中以 TAB(4个字符)缩进。
2.3长度
为便于阅读和理解,单个函数的有效代码长度当尽量控制在 100 行以内(不包括注释行), 当一个功能模块过大时往往造成阅读困难,因此当使用子函数等将相应功能抽取出来,这也有利于提高代码的重用度。
单个类也不宜过大,当出现此类情况时当将相应功能=-的代码重构到其他类中,通过组合等方式来调用,建议单个类的长度包括注释行不超过 1500 行。
尽量避免使用大类和长方法。
2.4行宽
页宽应该设置为 80 字符。一般不要超过这个宽度, 这会导致在某些机器中无法以一屏来完整显示, 但这一设置也可以灵活调整。在任何情况下, 超长的语句应该在一个逗号后或一个操作符前折行。一条语句折行后, 应该比原来的语句再缩进一个 TAB 或 4个空格,以便于阅读。
在书写SQL时,最好先在PL/SQL中先把语句写好,然后调用PL/SQL语句美化器进行美化。这个功能在PL/SQL6.0及以后版本中才提供。具体位置为:Edit菜单PL/SQL beautifier菜单。
行宽在WORKSHOP中的设置方法为:windows菜单Preferences菜单JAVAcode styleformatter,选择一个格式文件,点击“SHOW”按钮,修改红色框中的地方的值即可。
2.5间隔
类、方法及功能块间等应以空行相隔,以增加可读性,但不得有无规则的大片空行。 操作符两端应当各空一个字符以增加可读性。相应独立的功能模块之间可使用注释行间隔,并标明相应内容。
设置方法:windows菜单Preferences菜单JAVAcode styleformatter,选择一个格式文件,点击“SHOW”按钮,修改红色框中的两个页面中的值即可。
2.6对齐
关系密切的行应对齐,对齐包括类型、修饰、名称、参数等各部分对齐。连续赋值时当对齐操作符。当方法参数过多时当在每个参数后(逗号后)换行并对齐。 当控制或循环中的条件比较长时当换行(操作符前)、对齐并注释各条件。变量定义最好通过添加空格形成对齐,同一类型的变量应放在一起。
设置方法:windows菜单Preferences菜单JAVAcode styleformatter,选择一个格式文件,点击“SHOW”按钮。修改各变量的对齐在红色框中的地方。
参数过长时对齐设置在:
2.7括号
{}中的语句应该单独作为一行,左括号\"{\"当紧跟其语句后,右括号\永远单独作为一行且与其匹配行对齐。
不要在程序中出现不必要的括号,但有时为了增加可读性和便于理解,当用括号限定相应项。左括号是否换行等随个人习惯而定,若换行则当与其前导语句首字符对齐。
设置方法:windows菜单Preferences菜单JAVAcode styleformatter,选择一个格式文件,点击“SHOW”按钮。红色框中的TAB页可设置括号的对齐。
第3章 注释
3.1基本原则
➢ 注释应该增加代码的清晰度。代码注释的目的是要使代码更易于被其他开发人员理
解。
➢ 如果你的程序不值得注释,那么它很可能也不值得运行。
➢ 避免使用装饰性内容。
➢ 保持注释的简洁。
➢ 注释信息不仅要包括代码的功能,还应给出原因。
➢ 不要为注释而注释。
➢ 除变量定义等较短语句的注释可用行尾注释外,其他注释当避免使用行尾注释。
➢ 对类、方法、变量等的注释需要符合 JavaDoc 规范,对每个类、方法都应详细说明其功能、条件、参数等,并使用良好的 HTML 标记格式化注释,以使生成的 JavaDoc 易阅读和理解。
➢ 注释参考表
3.2类、接口注释
在类、接口定义之前当对其进行注释,包括类、接口的目的、作用、功能、继承于何种父类,实现的接口、实现的算法、使用方法、示例程序等。
3.3方法注释
依据标准 JavaDoc 规范对方法进行注释,以明确该方法功能、作用、各参数含义以及返回值 等。参数注释时当注明其取值范围等 返回值当注释出失败、错误、异常时的返回情况。 异常当注释出什么情况、什么时候、什么条件下会引发什么样的异常
3.4变量注释
变量注释主要是明确变量的作用;什么情况下可用,什么情况下不可用;不同情况下值取值有什么不同;如果值可枚举的话各个值的说明;如果是新增的变量,可能的话还需要说明是由谁新增的,新增时间以及新增原因。
类变量注释示例:
类常量注释示例:
函数内变量注释示例:
3.5代码块注释
代码块注释主要是说明代码块的功能;实现方法;注意细节等。
3.6修改注释
程序修改时,首先在类中添加修改注释,包括修改人,修改时间,修改原因以及修改
内容,如图:
对于需要被修改或移除的代码,在之前添加移除人,移除时间,移除开始分隔符及移除结束分隔符。
对于新增加的代码代码,格式如下:
如果修改的内容位于函数体内且变动比较小时,修改原函数的描述,注意事项,参数,返回值,异常等信息,并添加修改人修改时间,如下:
如果函数功能变化很大,则移除原方法,新增一个方法来实现代码修改。
3.7配置文件注释
为了保存配置文件在WEBLOGIC下运行正常,所有的配置文件只能选择不注释或者是用英文注释。
3.8JS注释
JS中注释可以有,但和方法注释等一样,要求准确,完善。
第4章 命名
4.1基本原则
规范的命名能使程序更易阅读,从而更易于理解。它们也可以提供一些标识功能方面的信息,有助于更好的理解代码和应用。
➢ 使用可以准确说明变量、字段、类、接口、包等的完整的英文描述符。例如,采用
类似 firstName,listAllUsers 或CorporateCustomer这样的名字,尽量不使用汉语拼音及不相关单词命名,虽然 Java 支持 Unicode 命名,但本规范规定对包、类、接口、 方法、变量、字段等不得使用汉字等进行命名。
➢ 采用该领域的术语。如果用户称他们的“客户”(clients) 为“顾客”(customers),那么就采用术语 Customer 来命名这个类,而不用 Client。
➢ 采用大小写混合,提高名字的可读性。一般应该采用小写字母,但是类和接口的名字的首字母,以及任何中间单词的首字母应该大写。包名全部小写。
➢ 尽量少用缩写,但如果一定要使用,当使用公共缩写和习惯缩写等,如实现(implement)可缩写成impl,经理(manager)可缩写成 mgr 等,具体参看附录之《常用缩写简表》,严禁滥用缩写。
➢ 避免使用长名字(最好不超过25个字母)。
➢ 避免使用相似或者仅在大小写上有区别的名字。
➢ 避免使用数字,但可用2代替 to,用4代替 for 等,如:go2Jsp。
4.2文件、包
➢ 文件名当与其类严格相同,所有单词首字母大写。
➢ 包名一般以项目或模块名命名,少用缩写和长名,一律小写。
➢ 基本包:com.hjh所有包、文件都从属于此包。
➢ 包名按如下规则组成: [基本包].[项目名].[模块名].[子模块名]...如:
Com.hjh.yys.hyfx.dao
➢ 目录参考结构如下:
目录说明
ProjectName 项目目录,当和项目名一致
/web 输出目录
/index.jsp 首页文件
/web-inf
/classes 类构建目录
/ lib 资源文件
/ struts 页面流程配置文件
/dwr.xml DWR配置文件
/web.xml 应用程序配置文件
/其它文件 CSS,JS,图片,及JSP文件
/src 源码目录
/java包和文件
/config 配置目录
/spring 配置文件信息
/hbm.xml hibernate配置信息
/property文件
/docs 文档目录
➢ 不得将类直接定义在基本包下,所有项目中的类、接口等都当定义在各自的项目和模块包中。
4.3类、接口
所有单词首字母大写。使用能确切反应该类、接口含义、功能等的词。一般采用名词。 接口可带 I 前缀或 able、ible、er 等后缀。推荐接口命名为:I前缀 + 模块名 + 业务名称或简称 + Service后缀。实现该接口的类文件名为:模块名 + 业务名称或简
称 + ServiceImp后缀。
4.4方法
方法的命名应采用完整的英文描述符,大小写混合使用:所有中间单词的第一个字母大写。 方法名称的第一个单词常常采用一个有强烈动作色彩的动词。取值类使用 get 前缀,设值类使用 set 前缀,判断类使用 is(has)前缀,保存操作类使用save前缀,删除操作使用delete前缀,查询数据采用query前缀。 例:getName(),setSarry(),isLogon() 方法。参数建议顺序:(被操作者,操作内容,操作标志,其他)
4.5变量
➢ 变量名当能反映变量的作用,便于其它程序员理解程序,而不是把程序搞的更复杂。
➢ 常量 采用完整的英文大写单词,在词与词之间用下划线连接,如:DEFAULT_VALUE。
➢ 变量和参数 对不易清楚识别出该变量类型的变量应使用类型缩写作其前缀,如字符串使用strXXX,boolean 使用 isXXX,hasXXX 等等。除第一各个单词外其余单词首字母大写。 对私有实例变量可使用_前缀,但在其存取方法中则应该将其前缀去掉。
➢ 组件/部件 应采用完整的英文描述符命名组件(接口部件),遵循匈牙利命名法则 如:btnOK,lblName。
➢ 集合 一个集合,例如数组和矢量,应采用复数命名来表示队列中存放的对象类型。命名应采用完整的英文描述符,名字中所有非开头的单词的第一个字母应大写,适当使用集合缩写前缀。如:Vector vProducts = new Vector(); //产品向量 Array aryUsers = new Array(); //用户列表
➢ 神秘的数 我们在程序里经常会用到一些量,它是有特定的含义的。例如,现在我们写一个薪金统计程序,公司员工有 50 人,我们在程序里就会用 50 这个数去进行各种各样的运算。在这 里,50 就是\"神秘的数\"。当别的程序员在程序里看到 50 这个数,将很难知道它的含义,造 成理解上的困难。在程序里出现\"神秘的数\"会降低程序的可读性、可维护性和可扩展性,故规定不得出现 此类\"神秘的数\"。避免的方法是把神秘的数定义为一个常量。注意这个常量的命名应该能表 达该数的意义,并且应该全部大写,以与对应于变量的标识符区别开来。例如上面 50 这个 数,我们可以定义为一个名为 NUM_OF_EMPLOYEES 的常量来代替。这样,别的程序员在读程序 的时候就可以容易理解了。
➢ 其他 命名时应使用复数来表示它们代表多值。如:orderItems。
4.6异常
异常类名由表示该异常类型的单词和 Exception 组成,如 ActionException。 异常实例一般使用 e、ex 等,在多个异常时使用该异常名或简写加 E,Ex 等组成,如:SQLEx,ActionEx
4.7命名约定表
第5章 声明
5.1 基本原则
声明的基本原则是遵守 Java 语言规范,并遵从习惯用法。
5.2 包
在导入包时当完全限制代码所使用的类的名字,尽量少用通配符的方式,但导入一些通用包, 或用到一个包下大部分类时,则可是使用通配符方式,如:
import org.skyinn.quasar.services.Service;
import java.util.*;
在WORKSHOP中导入包,可以通过CTRL+SHIFT+O来实现
5.3 类、接口
类、接口定义语法规范:
[可见性][('abstract'|'final')] [Class|Interface] class_name
[('extends'|'implements')][父类或接口名]{
}
如:
public class LoginAction extends BaseAction implemnets ActionListener {
}
5.4 方法
良好的程序设计应该尽可能减小类与类之间耦合,所遵循的经验法则是:尽量限制成员函数的可见性。如果成员函数没必要公有 (public),就定义为保护 (protected);没必要保护 (protected),就定义为私有 (private)。
方法定义语法规范:
[可见性][('abstract'|'final')] ['synchronized'][返回值类型] method_name(参数 列表)[('throws')][异常列表]{
// 功能模块
} 如:
public List listAllUsers() throws DAOException{
}
若有 toString(),equals(),hashCode(),colone()等重载自 Object 的方法,应将其放在类的最后。
声明顺序:
构造方法 静态公共方法 静态私有方法 受保护方法 私有方法 继承自 Object 的方法。
5.5 变量
字段定义语法规范: [(‘public’|’private’|’protected’)]
[(‘final’|’volatile’)][‘static’][‘transient’] [ ‘=’ expression] ‘;’
data_type field_name
若没有足够理由,不要把实例或类变量声明为公有。公共和保护的可见性应当尽量避免,所 有的字段都建议置为私有,由获取和设置成员函数(Getter、Setter)访问。
不允许“隐藏”字段,即给局部变量所取的名字,不可与另一个更大范围内定义的字段的名 \\字相同(或相似)。例如,如果把一个字段叫做 firstName ,就不要再生成一个局部变量叫做 firstName,或者任何易混肴的名字,如fistName。
数组声明时当将\"[]\"跟再类型后,而不时字段名后,如:
Integer[] ai = new Integer (2); //一个整数对象数组,用于...
Integer aj[] = new Integer (3); //不要用这种数组声明方式
一行代码只声明一个变量,仅将一个变量用于一件事。 声明顺序:
常量 类变量 实例变量 公有字段 受保护字段 私有字段
可以将私有变量声明在类或接口的最后。 注意受保护变量、私有变量、“包”变量间的区别。
第6章 使用
6.1文件、包
按照4.2中的目录结构来创建文件。包统一路径为:com.hjh.[模块名][子模快名][功能]来划分。
公司现在的功能分层方法一般为:
FORM层,在这层中主要包括用于页面显示及处理的字段及相应的GET,SET方法。如果页面可对列表进行编辑,则可添加从前台页面的列表转FORM中LIST的方法。
FORM层实现时要注意的几点:
➢ 非JAVA基本数据类型的字段,在GET方法中必须进行初始化。
➢ 用于接收从页面传入的查询条件的字段名,最好以query作前缀。
➢ 不要在一个FORM中包含多个相同意义的字段,这在使用中会引发问题,额外
增加程序的复杂度。
➢ 字段的使用不要超过字段定义时的功能。比如:queryNsrsbh在声明时的它的
功能为获取页面录入的查询条件,但很多人用着用着就把它作为当前纳税人使用。
ACTION层,在这层中我们主要处理两件事,根据页面动作调用相应SERVICE中的方法;指定返回页面。一般情况下,异常需要在此进行处理。
ACTION层实现时要注意的几点:
➢ 不要把SERVICE中应该执行的代码写在ACTION中。
➢ 也不要把FORM中应该执行的代码写在ACTION中。
➢ 在保存,删除等操作之后,如果成功记得进行成功提示,如果有错误则由
ERROR.JSP来处理。
SERVICE接口及实现。这里主要实现业务逻辑及相关功能。
开发时要注意几点:
➢ 哪些方法需要在接口中定义,哪些方法应该设置为PRIVATE,应该谨慎处理。
➢ 把重复的功能实现定义为私有函数,比如页面初始化。
➢ 在功能实现时请尽可能的减少数据库的调用次数,尽量多用缓存,尤其是在循环
和递归中执行数据库操作的行为应该尽量避免。
DAO及实现
➢ 单表及简单的表操作,可以使用HIBERNATE来实现,以提高工作效率。
➢ 复杂SQL使用JDBC来实现
➢ SQL语句书写时请参考第8章SQL语句,提高SQL语句的执行效率。
6.2类与接口
6.2.1 基本原则
类的划分粒度,不可太大,造成过于庞大的单个类,也不可太细,从而使类的继承太深。一 般而言,一个类只做一件事;另一个原则是根据每个类的职责进行划分,比如用 User 来存放用户 信息,而用 UserDAO 来对用户信息进行数据访问操作(比如存取数据库),用 UserBroker 来封装用户信息的业务操作等等。
多使用设计模式,随时重构。 多个类中使用相同方法时将其方法提到一个接口中或使用抽象类,尽量提高重用度。 将不希望再被继承的类声明成 final,例如某些实用类,但不要滥用 final,否则会对系统的
可扩展性造成影响。 将不希望被实例化的类的缺省构造方法声明成 private。
6.2.2 抽象类与接口
一般而言:接口定义行为,而抽象类定义属性和公有行为,注意两者间的取舍,在设计中, 可由接口定义公用的行为,由一个抽象类来实现其部分或全部方法,以给子类提供统一的行为定 义,可参考 Java 集合等实现。
多使用接口,尽量做到面向接口的设计,以提高系统的可扩展性。
6.2.3 继承与组合
尽量使用组合来代替继承,一则可以使类的层次不至于过深,而且会使类与类,包与包之间 的耦合度更小,更具可扩展性。
6.2.4 构造函数和静态工厂方法
当需要使用多个构造函数创建类时,建议使用静态工厂方法替代这些构造方法(参考
《Effictive Java》 Item1),例如:
参看String,Boolean的实现等:String.valueOf(Long l),Boolean.valueOf(String)...
6.2.5 toString(),equals(),hashCode()...
每个类都应该重载 toString()方法,以使该类能输出必要和有用的信息等。
若一个类需要重载 equals()方法,则必须同时重载 hashCode()方法实现方式参考
《Effictive Java》Item7,Item8
6.2.6 Singleton Class
单例类使用如下方式声明,并将其缺省构造方法声明成 private:
单例类若需要实现序列化,则必须提供 readResolve()方法,以使反序列化出来的类仍然是 唯一的实例,参加《Effictive Java》 Item57。
6.3方法
6.3.1基本原则
一个方法只完成一项功能,在定义系统的公用接口方法外的方法应尽可能的缩小其可见性。 避免用一个类实例去访问其静态变量和方法。
避免在一个较长的方法里提供多个出口:
//不要使用这钟方式,当处理程序段很长时将很难找到出口点
if(condition){
return A;
}else{
return B;
}
//建议使用如下方式
String result = null;
if(condition){
result = A;
}else{
result = B;
}
return result;
6.3.2参数
避免过多的参数列表,尽量控制在 5 个以内,若需要传递多个参数时,当使用一个容纳这些 参数的对象进行传递,以提高程序的可读性和可扩展性。
参数类型和返回值尽量接口化,以屏蔽具体的实现细节,提高系统的可扩展性,例如:
public void joinGroup(List userList){}
public List listAllUsers(){}
6.3.3返回值
返回值需要注意二点:一个是方法说明中的返回值必须明确并准确,并与方法的实现返回值匹配。有一种比较常见的错误如下:
这个方法,它的设计初衷是当数据库中存在相应的记录时返回BO对象,那不存在时应当为空;但现在不论有没有从数据库中找到相应记录,都会从返回一个不为空的BO对象。当调用者以判断返回是否为NULL来判断数据库中是否有相应记录就会引发问题。
6.4变量
JAVA开发调试或实现应用中出现最多的一个错误估计就是NULLPOINTERERROR(空指针问题)了,所以在使用变量时要额外注意。
6.4.1基本原则
变量在声明之后必须进行初始化。
如果是变量是非基本类型的实例,则在使用前必须进行是否为NULL检测。
6.4.2变量验证
如果为字符串,在验证之前最好先Trim一下,然后判断是否为NULL及是否等于””。
在某些特殊情况下,如果这个字符串其值有特定的含义,比如代表的是年份,则还需要验证是否为四位的数字。
如果为数组或集合,则在判断是否为NULL之外一般还需要判断数组的长度是否大于0。
6.5表达式与语句
6.5.1 基本原则
表达式和语句当清晰、简洁,易于阅读和理解,避免使用晦涩难懂的语句。 每行至多包含一条执行语句,过长当换行。 避免在构造方法中执行大量耗时的初始化工作,应当将这中工作延迟到被使用时再创建相应资源,如果不可避免,则当使用对象池和 Cache 等
技术提高系统性能。 避免在一个语句中给多个变量赋相同的值。它很难读懂。 不要使用内嵌(embedded)赋值运算符试图提高运行时的效率,这是编译器的工作。 尽量在声明局部变量的同时初始化。唯一不这么做的理由是变量的初始值依赖于某些先前发生的计算。 一般而言,在含有多种运算符的表达式中使用圆括号来避免运算符优先级问题,是个好方法。即使运算符的优先级对你而言可能很清楚,但对其他人未必如此。你不能假设别的程序员和你一样清楚运算符的优先级。
不要为了表现编程技巧而过分使用技巧,简单就好。
6.5.2 控制语句
判断中如有常量,则应将常量置与判断式的右侧。如:
if ( true == isAdmin())... if ( null == user)...
尽量不使用三目条件判断。
所有 if 语句必须用{}包括起来,即便是只有一句:
if (true){
//do something......
}
//不要使用这种
if (true)
i = 0;
当有多个 else 分句时当分别注明其条件,注意缩进并对齐,如:
//先判断 i 是否等于 1
if (i == 1){//if_1
//.....
}//然后判断 i == 2
else if (i == 2){
//i == 2 说明。。。。。。
j = i;
}//如果都不是(i > 2 || i < 1)
else{
//说明出错了
//....
}//end if_1
过多的 else 分句请将其转成 switch 语句或使用子函数。
每当一个 case 顺着往下执行时(因为没有 break 位置添加注 释。如:
switch (condition) {
case ABC:
//statements;
//继续下一个 CASE
case DEF:
//statements;
break;
case XYZ:
//statements;
语句),通常应在 break 语句的
break;
default:
//statements;
break;
}//end switch
6.5.3 循环语句
循环中必须有终止循环的条件或语句,避免死循环。
当在 for 语句的初始化或更新子句中使用逗号时,避免因使用三个以上变量,而导致复杂度 提高。若需要,可以在 for 循环之前(为初始化子句)或 for 循环末尾(为更新子句)使用单独的语句。因为循环条件在每次循环中多会执行一次,故尽量避免在其中调用耗时或费资源的操作,比 较一下两种循环的差异:
//不推荐方式
while(index < products.getCount()){
//每此都会执行一次 getCount()方法,
//若此方法耗时则会影响执行效率
//而且可能带来同步问题,若有同步需求,请使用同步块或同步方法
}
//推荐方式
//将操作结构保存在临时变量里,减少方法调用次数
final int count = products.getCount();
while(index < count){
}
尽量不要在循环时执行数据库操作,这样会对程序的性能造成非常大的影响。
6.6错误与异常
6.6.1 基本原则
通常的思想是只对错误采用异常处理:逻辑和编程错误,设置错误,被破坏的数据,资源耗 尽,等等。
通常的法则是系统在正常状态下以及无重载和硬件失效状态下,不应产生任何异常。 最小化从一个给定的抽象类中导出的异常的个数。 对于经常发生的可预计事件不要采用异常。
不要使用异常实现控制结构。 确保状态码有一个正确值。 在本地进行安全性检查,而不是让用户去做。
若有 finally 子句,则不要在 try 块中直接返回,亦不要在 finally 中直接返回。
6.6.2已检查异常与运行时异常
已检查异常必须捕捉并做相应处理,不能将已检查异常抛到系统之外去处理。 对可预见的运行时异常当进行捕捉并处理,比如空指针等。通常,对空指针的判断不是使用
捕捉 NullPointException 的方式,而是在调用该对象之前使用判断语句进行直接判断,如:
//若不对 list 是否为 null 进行检查,则在其为 null 时会抛出空指针异常
if(null != list && 0 < list.size()){
for(int i = 0; i < list.size(); i++){
}
}
建议使用运行时异常(RuntimeException)代替已检查异常(CheckedException),请参考网络资源以对此两种异常做更深入理解。
6.6.3 异常的捕捉与处理
捕捉异常是为了处理它,不要捕捉了却什么都不处理而抛弃之,最低限度当向控制台输出当 前异常,如果你不想处理它,请将该异常抛给它的调用者,建议对每个捕捉到的异常都调用 printStackTrace()输出异常信息,避免因异常的湮没。
多个异常应分别捕捉并处理,避免使用一个单一的 catch 来处理。如:
try {
//do something
}catch(IllegalStateException IllEx){
IllEx.printStackTrace();
//deal with IllEx
}catch(SQLException SQLEx){
SQLEx.printStackTrace();
throw SQLEx; //抛给调用者处理
}finally{
//释放资源
}
6.7日志
6.7.1 基本原则
异常除了需要打印到控制台外,还需要写入到日志文件中。
6.7.2日志打印
使用DOM4J来作为日志的输出。
第7章 性能与安全
7.1基本原则
性能的提升并不是一蹴而就的,而是由良好的编程积累的,虽然任何良好的习惯和经验所提 升的性能都十分有限,甚至微乎其微,但良好的系统性能却是由这些习惯等积累而成,不积细流,无以成江海!
7.2 String 与 StringBugffer
不要使用如下 String 初始化方法:
String str = new String(“abcdef”); 这将产生两个对象,应当直接赋值:
String str = “abcdef”;
在处理可变 String 的时候要尽量使用 StringBuffer 类,StringBuffer 类是构成 String 类的基础。String 类将 StringBuffer 类封装了起来,(以花费更多时间为代价)为开发人员提 供了一个安全的接口。当我们在构造字符串的时候,我们应该用 StringBuffer 来实现大部分的 工作,当工作完成后将 StringBuffer 对象再转换为需要的 String 对象。比如:如果有一个字 符串必须不断地在其后添加许多字符来完成构造,那么我们应该使用 StringBuffer 对象和她的 append() 方法。如果我们用 String 对象代替 StringBuffer 对象的话,将会花费许多不必要的创建和释放对象的 CPU 时间。
7.3集合
避免使用 Vector 和 HashTable 等旧的集合实现,这些实现的存在仅是为了与旧的系统兼容, 而且由于这些实现是同步的,故而在大量操作时会带来不必要的性能损失。在新的系统设计中不当出现这些实现,使用 ArrayList 代替 Vector,使用 HashMap 代替 HashTable。
若却是需要使用同步集合类,当使用如下方式获得同步集合实例:
Map map = Collections.synchronizedMap(new HashMap());
由于数组、ArrayList 与 Vector 之间的性能差异巨大(具体参见《Java fitball》),
故在 能使用数组时不要使用 ArrayList,尽量避免使用 Vector。
7.4对象
避免在循环中频繁构建和释放对象。 不再使用的对象应及时销毁。 如无必要,不要序列化对象。
7.5同步
在不需要同步操作时避免使用同步操作类,如能使用 ArrayList 时不要使用 Vector。 尽量少用同步方法,避免使用太多的 synchronized 关键字。 尽量将同步最小化,即将同步作用到最需要的地方,避免大块的同步块或方法等。
7.6 final
将参数或方法声明成 final 可提高程序响应效率,故此: 注意绝对不要仅因为性能而将类、方法等声明成 final,声明成 final 的类、方法一定要确信不再被继承或重载! 不需要重新赋值的变量(包括类变量、实例变量、局部变量)声明成 final
所有方法参数声明成 final 私有(private)方法不需要声明成 final,若方法确定不会被继承,则声明成 final
7.7垃圾收集和资源释放
不要过分依赖 JVM 的垃圾收集机制,因为你无法预测和知道 JVM 在什么时候运行 GC。 尽可能早的释放资源,不再使用的资源请立即释放。
可能有异常的操作时必须在 try 的 finally 块中释放资源,如数据库连接、IO 操作等:
Connection conn = null;
try{
//do something
}catch(Exception e){ //异常捕捉和处理
e.printStackTrack();
}finally{
//判断 conn 等是否为 null if(null != conn){
conn.close();
}
}//end try...catch...finally
第8章 第9章
SQL语句 页面
因篇幅问题不能全部显示,请点此查看更多更全内容