Java开发规范(公司规范)
第1章 序言
本规范的目的在于:建立一个可行可操作的编程标准、约定和指南,以规范公司java代码研发工作。
2013年为公司的质量年,为了提高公司研发能力,该规范的制定是为了规范java代码开发,提高java开发质量,从代码的层面规范并提高java项目的研发水平。该规范由运营中心技术小组制定,运营中心技术小组将结合PMD检查工具以及相应的检查工具,组织技术监控人员对重点项目以及新的java项目定期检查,对代码质量进行评估,对代码质量较差限期整改,并报运营中心备案作为项目考核依据。
本规范适用于2013年公司java代码研发规范。本规范的内容包括两个方面:java开发一般规范,以及java代码开发安全性规范。Java代码开发一般规范主要从java基本语法,代码格式,耦合性以及
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
方面,以及代码质量因子等进行描述;java代码开发安全性规范主要从sql注入,资源注入,跨站脚步,安全边界违例,系统信息泄露进行描述。
为了方便并配合PMD检查工具等相应检查工具,方便开发者针对违规代码进行调整,本规范中java一般开发规范描述形式将结合PMD,并提供示例代码,其形式如下:
, 规范描述:
, PMD规则名称:
, PMD级别(注1):
, 违规示例代码:
, 合法示例代码:
本规范中java安全开发规范部分将结合具体项目,对出现安全隐患的代码进行
分析
定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析
,以及相应的解决办法和思路上进行分析,其具体格式如下:
, 风险及危害:
, 应对措施:
, 非安全代码示例
, 安全代码示例
本规范解释权归运营中心技术小组,属于运营中心为了提供公司研发水平以及质量的一系列措施中的一部分,在后续的版本中将根据具体需要进行修改以及调整。
注1:PMD级别分为5级
Error high 必须修改
Error 不修改的项需要进行说明
Warning high 代码中该项每千行代码不能多于2%;
Warning 参考
Information 参考
注2:对于Error级别需要项目组通过以下文字说明: 文件名 代码行数 触发PMD规则 不修改原因 技术小组审核意见
技术小组审核后给出相应的整改意见,对于有争议的问
题
快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题
,可直接与运营中心技术小组领导成员沟通。
第2章 要求
气象局项目组的所有java开发人员,编写的代码必须满足第三章的所有规范(每个标题为一个规范)。项目组成员之间每周或每月互相检查对方编写的代码,若发现问题,要求对方及时更正。项目经理应该随时抽查、并最终审查代码,保证代码的规范性。
第3章 java一般性研发规范
3.1 代码格式
3.1.1 包、类、方法的命名规范:
, 规范描述:
包,类,方法命名只能为27个英文字符以及数字,不能包括特殊字符例如-,
_,$等;
包命名,首字符必须小写;
类命名,首字符必须大写;
方法命名,首字符必须小写;
常量命名,必须全部大写;
变量,以及属性命名,首字符必须小写;
在类中非创建方法其命名应避免与类名一致;
在类中属性的命名应避免与类名一致;
在同一类中属性命令应避免与方法命名一致;
在方法中命名临时变量时应避免与方法的参数名一致; , PMD规则名称:
AvoidDollarSigns
PackageCase
ClassNamingConventions
MethodNamingConventions
SuspiciousConstantFieldName
VariableNamingConventions
MethodWithSameNameAsEnclosingClass
AvoidFieldNameMatchingTypeName
MisleadingVariableName
, 规则级别:
Error High
warn High
warn High
warn High
warn High
Error High
Error High
Error High
, 违规示例代码:
1、常量、变量命名
public static final int my_num = 0; //常量应大写
public String MyTest = ""; //变量命名,首字符小写 DataModule DMTest = new DataModule();//变量命名,首字符小写 2、方法命名
public class Foo {
public void FooStuff() {
}
}
3、类命名:首字符应大写
public class foo {}
4、非法使用特殊字符命名
public class Fo$o { // yikes!
}
5、非创建方法命名应避免与类名一致
public class MyClass {
// this is bad because it is a method
public void MyClass() {}
// this is OK because it is a constructor
public MyClass() {}
}
6、方法中临时变量的命名应避免与其参数一致:
public void bar(String m_baz) { // Bad
int m_boz = 42; // Bad }
7、在类中属性的命名应避免与类名一致:
public class Foo extends Bar {
// There's probably a better name for foo
int foo;
}
8、在同一类中属性命名应避免与方法命名一致:
public class Foo {
Object bar;
// bar is data or an action or both?
void bar() {
}
}
, 合法代码示例:
1、常量、变量命名:
public static final int MY_NUM = 0; //
public String myTest = "";
DataModule dmTest = new DataModule();
2、方法命名:首字符应小写
public class Foo {
public void fooStuff() {
}
}
3、类命名:首字符应大写
public class Foo {}
3.1.2 方法的命名应注意避免与java中具有特殊意义的名称例如equals,
hashCode,clone,finalizer等冲突
, 规范描述:
在java中某些方法是具有特殊意义的,例如boolean equals(Object o)是比较两个对象是否相等;int hashCode()取得hash值,主要用于hash表;Object clone()用于复制对象;void finalizer()用于该类实例化的对象释放时系统调用释放该对象使用的资源。这些方法具有固定的形参格式,固定的返回值,不能被其他形式或者用于其他方面的方法override,否则将降低代码可读性,并为代码维护带来隐患。
, PMD规则名称:
SuspiciousEqualsMethodName
SuspiciousHashcodeMethodName;
FinalizeOverloaded;
BooleanGetMethodName;
, 规则级别:
Error High
Error High
Error High
Error High
, 违规示例代码:
1、可疑的equals方法命名
public class Foo {
public int equals(Object o) {
// oops, this probably was supposed to be boolean equals
}
public boolean equals(String s) {
// oops, this probably was supposed to be equals(Object)
}
}
2、可疑的hashCode命名
public class Foo {
public int hashCode(int value) {
// oops, this probably was supposed to be hashCode
}
}
, 合法代码示例:
、正确的equals方法命名 1
public class Foo {
public boolean equals(Object o) {
// oops, this probably was supposed to be boolean equals
}
}
2、正确的hashCode命名
public class Foo {
public int hashCode() {
// oops, this probably was supposed to be hashCode
}
}
注:一般来说override hashCode方法为了避免键值冲突,提高hash表的查询效率,可采用37乘法原则,例如某javabean中包含两个关键属性str1,str2,str3该关键属性不能为空,这其hash值按以下算法获得:str1.hashCode()+str2.hashCode()*37+str3.hashCode()*37*37。 3.1.3 Java bean中取得boolean类型的属性值必须使用is****形式命名 , 规范描述:
对于java bean来说,get***是取得该bean的属性值,set***为设置该bean的属性值,is***是获得该bean中为boolean类型的属性值,这些方法对java bean来说是具有特殊意义,如果命名不规范将导致在使用java bean内置方法时出现取值,或者设值不成功。
, PMD规则名称:
BooleanGetMethodName
, 规则级别:
Error High
, 违规示例代码:
public boolean getFoo(); // bad , 合法代码示例:
public boolean isFoo(); // ok
3.1.4 if,else,while,for等必须使用{} , 规范描述:
If,else,while,for等分支循环语句,必须使用{}将业务处理逻辑包含在
内,这样可大大提高代码可读性,有利于后续代码维护。 , PMD规则名称:
IfStmtsMustUseBraces
WhileLoopsMustUseBraces
IfElseStmtsMustUseBraces
ForLoopsMustUseBraces , 规则级别:
warn High
, 违规示例代码:
1、if语句违例代码
if (foo) x++;
2、else语句违例代码
if (foo)
x++
else
x--;
、while语句违例代码 3
while(x<100)
x++;
4、for语句违例代码
for(int i=0;i<10;i++)
x++;
, 合法代码示例:
1、if语句
if (foo){
x++;
}
2、else语句
if (foo){
x++
}else{
x--;
}
3、while语句
while(x<100){
x++;
}
5、for语句
for(int i=0;i<10;i++){
x++;
}
3.1.5 类必须包含在包里,禁止出现无包的类
, 规范描述:
包是java中类所在命名空间,用于类载入时,虚拟机快速定位并查找该类;如果一个无包类,在类载入时,耗时较多,并且很可能无法找到该类。 , PMD规则名称:
NoPackage
, 规则级别:
error High
3.1.6 类和方法必须拥有注释,注释量占总体代码25%以上,类头部,以及
方法头部的注释应符合javadoc标准。
, 规范描述:
注释多少是评价代码质量好坏的一个标准,25%是符合国际上对java注释的标准;对于类头部注释,方法头部注释符合javadoc标准,可java工具自动根据源码生成相应的java帮助文档。对于类头部注释需要包含以下信息:该类的主用功能,作者,以及创建时间等信息;对于方法头部注释需要包含以下信息:该方法的主要功能,以及参数类型含义,返回值类型含义等等。 , 合法代码注释示例
1、类头部注释规范
/**
* 实时数据文件解析:读取实时数据文件,对其内容进行解析,生成符合格式以及标准单位的数据集合
* @author wangliuyi
* @version 1.0
* @since 2009-05-15
*/
public class DataFileParse{
2、方法头部注释规范
/**
* 判断该时间是否在统计时区里面
* @param time long 从实时采集文件中提取的时间,该时间为格林威治时间,单位为毫秒 * @return boolean true:表示该时间在合法的时间区内 false:表示该时间不合法 */
public boolean checkStatTimeZone(long time)
3、属性以及方法内部的注释通过“//”注释
public class GeneralStat implements IStat {
//解析数据格式的分隔符号
private String separator = ",";
//开始统计序号
private int startNum = 1;
3.2 基本语法
3.2.1 不能随意捕捉异常,原则上谁捕捉谁处理
, 规范描述:
Java程序运行过程中产生异常,意味着有错误产生,捕捉该异常,就需要对该异常进行处理:例如
记录
混凝土 养护记录下载土方回填监理旁站记录免费下载集备记录下载集备记录下载集备记录下载
日志,事务回滚等,如果仅捕获而不处理,人为的屏蔽异常,调用该函数,可能为调用者带来困惑,调用者极可能认为该方法正常运行而做出错误的判断。
一般来说,异常处理机制属于应用程序总体框架的一部分,一个良好的异常处理机制可以避免系统产生的一些不可预测的结果,并提高代码可读性,可维护性,从而提高代码的质量。本规则要对异常处理进行检查,对一些捕捉后不处理,或者直接将该异常抛出等进行预警。
, PMD规则名称:
EmptyCatchBlock
, 规则级别:
Warn High
, 违规示例代码:
public void doSomething() {
try {
doSomething……;
} catch (IOException ioe) {
// 获取异常后没有做任何处理
}
}
, 合法代码示例:
public static int parseInt(String value, int defaultValue)
{
if (isNull(value))
{
return defaultValue;
}
try
{
return Integer.parseInt(value.trim());
}
catch (Exception ex)
{
//记录日志
Log.warn(“转换异常”,ex);
//异常后返回缺省值
return defaultValue;
}
}
3.2.2 if,while,try,finally,switch , synchronized , static
instantiation 里面应有相应的逻辑处理,不能为空。
, 规范描述:
在if,while,try,finally,switch,synchronized,static Initializer中处理
逻辑部分如果为空,很可能这段代码无任何作用,是段废弃的代码,这段代码的
存在不仅对代码维护带来疑惑,降低了整体的代码质量。 , PMD规则名称:
EmptyIfStmt
EmptyWhileStmt
EmptyTryBlock
EmptyFinallyBlock
EmptySwitchStatements
EmptySynchronizedBlock
EmptyStaticInitializer , 规则级别:
Warn High
, 违规示例代码:
1. if语句中为空
if (foo){
}
2. while语句中为空
while(x<100)
{
}
3. try,finally中为空
try{
}finally{
}
4. switch中为空
switch(value){
}
5. synchronized中为空
synchronized(this){
}
6. static Initializer为空
static{
}
3.2.3 在处理循环中,不能在程序中人为的改变步长。
, 规范描述:
在循环中对步长变量人为的改变,很有可能丧失对步长的控制,导致运行时出现一些不可预测的结果。该规则是限制开发者对这种场景的使用,毕竟步长在多个地方改变,开发者很容易没有考虑全面,导致在特殊情况下出错。 , PMD规则名称:
JumbledIncrementer
, 规则级别:
Error
, 违规示例代码:
1. 上述代码会陷入死循环
public void foo() {
for (int i = 0; i < 10; i++) {
for (int k = 0; k < 20; i++) {
System.out.println("Hello");
}
}
3.2.4 将简单类型int,short,float,double等转化成字符串时,需使用
其对应类的toString方法。
, 规范描述:
将java中简单类型转换成字符串时,如果采用先转换成对应的类型的对象,然后通过值对象转换成字符串,该过程将产生两个对象的创建,而直接采用对应类型的toString方法,只产生一个对象的创建,其效率是前者的两倍。
, PMD规则名称:
UnnecessaryConversionTemporary , 规则级别:
Error High
, 违规示例代码:
1、 整形转字符
int value=1;
String v=new Integer(value).toString(); 2、 短整形转字符
short value=1;
String v=new Short(value).toString(); 3、 浮点转字符
float value=1.2f;
String v=new Float(value).toString(); 4、 双精度浮点转字符
double value=1.2d;
String v=new Double(value).toString(); , 合法代码示例:
1、 整形转字符
int value=1;
String v= Integer.valueOf(value);
2、 短整形转字符
short value=1;
String v= Short.valueOf( value);
3、 浮点转字符
float value=1.2f;
String v= Float.valueOf( value);
4、 双精度浮点转字符
double value=1.2d;
String v= Double.valueOf(value;
3.2.5 javaBean中hashCode,以及equals方法必须同时override。 , 规范描述:
HashCode是生成hash值,可用于hash表中主键的查找,equals是比较两个对象是否相等,缺省的hashCode以及equals只能针对同一引用的对象,如果为不同的引用的对象,虽然其值是相等,但使用hashCode却是不同的值,而使用equals返回的也是false。在某些场合中,例如将某javabean对象作为hash表的主键值,或者判断某对象是否在集合中,如果不实现hashCode,以及equals
会得到不可预测的结果。
, PMD规则名称:
OverrideBothEqualsAndHashCode
, 规则级别:
Error High
, 违规示例代码:
//该AgcDataInfo没有override equals方法
public class AgcDataInfo
{
Public AgcDataInfo(String planUnitNo)
{
if(planUnitNo!=null)
this.planUnitNo = planUnitNo;
}
//机组名称
String planUnitNo=””;
/**
* 生成hash值
*/
public int hashCode()
{
return this.getPlanUnitNo().hashCode();
}
/**自动生成get,set方法
public String getPlanUnitNo()
{
return planUnitNo;
}
public void setPlanUnitNo(String planUnitNo)
{
if(planUnitNo!=null)
this.planUnitNo = planUnitNo;
}
}
public void main(String[] args) {
Collection v=new Vector();
Map map=new Hashtable();
AgcDataInfo t1=new AgcDataInfo(“test”);
AgcDataInfo t2=new AgcDataInfo(“test”);
v.add(t1);
map.put(t1,“test“);
map.put(t2,“test“);
//false而不是true
System.out.println(v.contains(t2));
//2而不是1
System.out.println(map.size()); }
, 合法代码示例:
public class AgcDataInfo
{
Public AgcDataInfo(String planUnitNo)
{
if(planUnitNo!=null)
this.planUnitNo = planUnitNo;
}
//机组名称
String planUnitNo=””;
/**
* 比较等式,比较值为下达时间,下达功率,机组名称
*/
public boolean equals(Object o)
{
if (o instanceof AgcDataInfo)
{
AgcDataInfo data = (AgcDataInfo) o;
return his.getPlanUnitNo().equals(data.getPlanUnitNo());
}
return false;
}
/**
* 生成hash值
*/
public int hashCode()
{
return this.getPlanUnitNo().hashCode();
}
/**自动生成get,set方法
public String getPlanUnitNo()
{
return planUnitNo;
}
public void setPlanUnitNo(String planUnitNo)
{
if(planUnitNo!=null)
this.planUnitNo = planUnitNo;
}
}
public void main(String[] args)
{
Collection v=new Vector();
Map map=new Hashtable();
AgcDataInfo t1=new AgcDataInfo(“test”);
AgcDataInfo t2=new AgcDataInfo(“test”);
v.add(t1);
map.put(t1,“test“);
map.put(t2,“test“);
//true
System.out.println(v.contains(t2));
//1
System.out.println(map.size());
}
3.2.6 懒式方式创建对象:不能采用双检查惯用法
, 规范描述:
双检查一般用于c,c++懒式方式获得资源时惯用模式,但在java中该模式是不适用的,因为java创建对象时,先将对象创建后,直接将指针赋予给变量,然后才进行后续的初始化,在初始化这段空白期中,如果另外的线程获得该对象的引用,调用该对象,会产生一些不可预测的结果。
, PMD规则名称:
DoubleCheckLock
, 规则级别:
Error High
, 违规示例代码
public class Foo {
Object baz;
Object bar() {
if(baz == null) { //baz may be non-null yet not fully created
synchronized(this){
if(baz == null){
baz = new Object();
}
}
}
return baz;
}
}
, 合法代码示例:
public class Foo{
Object baz;
Object bar() {
synchronized(this){
if(baz == null){
baz = new Object();
}
}
return baz;
}
}
3.2.7 不能在finally中返回值。
, 规范描述:
finally中是必须执行的程序块,如果在里面返回,则表示该方法返回值只
能为这个,其他地方返回值可能无效。
, PMD规则名称:
ReturnFromFinallyBlock , 规则级别:
Error High
, 违规示例代码:
public int foo(String value) {
try {
return Integer.parseInt(value);
} catch (Exception e) {
return 0;;
} finally {
return -1; // Very bad.
}
}
, 合法代码示例:
public int foo(String value) {
int ret=0;
try {
ret= Integer.parseInt(value);
} catch (Exception e) {
ret= 0;
} finally {
//处理其他事宜
……
}
return ret; // Very good.
}
3.2.8 Boolean实例化时,应用使用Boolean.valueOf,Boolean.TRUE,
Boolean.FALSE。
, 规范描述:
采用Boolean.valueOf,Boolean.TRUE,Boolean.FALSE进行实例化具有更高的效率。 , PMD规则名称:
BooleanInstantiation
, 规则级别:
Error High
, 违规示例代码:
Boolean bar = new Boolean("true");//效率较低
, 合法代码示例:
// just do a Boolean bar = Boolean.TRUE;
Boolean buz = Boolean.valueOf(false);
// just do a Boolean buz = Boolean.FALSE;
3.2.9 Integer,Byte,Short,Long等实例化时,应用使用valueOf , 规范描述:
Integer,Byte,Short,Long实例化时使用valueOf具有更高的效率。 , PMD规则名称:
IntegerInstantiation
ByteInstantiation
ShortInstantiation
LongInstantiation
, 规则级别:
Error High
, 违规示例代码:
Integer v=new Integer(1);
Byte v=new Byte(1);
Short v=new Short(1);
Long v=new Long(1);
, 合法代码示例:
Integer v= Integer.valueOf(1);
Byte v=new Byte.valueOf(1);
Short v= Short.valueOf(1);
Long v= Long.valueOf(1);
3.2.10 对于多个if语句嵌套的情况下能够整合尽量整合。 , 规范描述:
对于多个if语句嵌套的情况下能够整合必须根据情况整合。 , PMD规则名称:
CollapsibleIfStatements , 规则级别:
Error
, 违规示例代码:
void bar() {
if (x) {
if (y) {
// do stuff
}
}
}
, 合法代码示例:
void bar() {
if (x&y)
{
// do stuff
}
}
3.2.11 override function,不能只有super.function语句,否则视为无效
代码
, 规范描述:
Over ride function则表示为该方法定义新的行为,如果仅仅super.function(),则没有任何意义,该处代码视为废弃代码。。 , PMD规则名称:
UselessOverridingMethod
, 规则级别:
Error High
, 违规示例代码:
public class Foo {
public void foo(String bar) {
super.foo(bar);
//Why bother overriding?
}
, 合法代码示例:
3.2.12 Collection.toArray的注意事项。
, 规范描述:
对于Collection接口来说,使用toArray转数据时,如果没有指明类型,将返回Object[],而不能使用类似(Integer[])list.toArray()进行强转成其他类型的数组,需要类似toArray(new Integer[list.size()])方式进行转换。 , PMD规则名称:
ClassCastExceptionWithToArray
, 规则级别:
Error High
, 违规示例代码:
Collection c=new ArrayList();
Integer obj=new Integer(1);
c.add(obj);
// this would trigger the rule (and throw a ClassCastException
if executed)
Integer[] a=(Integer [])c.toArray(); , 合法代码示例:
Collection c=new ArrayList();
Integer obj=new Integer(1);
c.add(obj);
// this wouldn't trigger the rule
Integer[] b=(Integer [])c.toArray(new Integer[c.size()]);
3.2.13 对于BigDecimal方法,应避免使用float值,double值进行创建,
应使用字符串形式创建。
, 规范描述:
对于BigDecimal,直接使用float,double创建时,因为精度不同会发生变化,例如0.1,会变成.1000000000000000055511151231257827021181583404541015625,这样会导致业务计算造成偏差。
, PMD规则名称:
AvoidDecimalLiteralsInBigDecimalConstructor
, 规则级别:
Error High
, 违规示例代码:
// this would trigger the rule
BigDecimal bd=new BigDecimal(1.123); , 合法代码示例:
// this wouldn't trigger the rule
BigDecimal bd=new BigDecimal("1.123");
3.2.14 String,BigDecimal,BigInteger等值类型调用replace,add等方法
的注意事项。
, 规范描述:
String,BigDecimal,BigInteger为值类型,当调用replace,replaceAll对字符串中替代函数,BigDecimal,BigIneger等add运算函数,会生成一个结果值对象返回,而不是修改本身调用者对象,该规则正是在这方面进行检查。 , PMD规则名称:
UselessOperationOnImmutable , 规则级别:
Error High
, 违规示例代码:
BigDecimal bd=new BigDecimal(10);
bd.add(new BigDecimal(5)); // bd仍然为10
, 合法代码示例:
BigDecimal bd=new BigDecimal(10); bd = bd.add(new BigDecimal(5)); // bd为15
3.2.15 需要注意的引起NullException的语句。
, 规范描述:
对空指针对象进行操作时,会抛出NullException异常,该规则则是在代码编写以及代码健全性上避免这些导致空指针异常的场景,规则如下:
使用equals时,常量应该放在前面,例如常量.equals(对象);
判非空:string!=null&&string.length()>0;
判空: string==null||string.length()<=0;
执行类似equals语句:a!=null&&a.equals(b);
禁止使用equals(null)方式
, PMD规则名称:
MisplacedNullCheck
UnusedNullCheckInEquals
BrokenNullCheck
, 规则级别:
Error High
, 违规示例代码:
1、 空指针检查错位
if (a.equals(baz) && a != null){
„„
};
if (a.equals(baz) || a == null){
„„
};
2、 无用的空指针检查
if (a!=null && b.equals(a)) { // 该处虽然对a对象进行了检查,但没有对b进行检查
//whatever
}
3、 常见的判空,判非空代码编写上的错误
//判非空,却使用了||
if (string!=null || !string.equals("")){
return string;
}
//判空却用了&&
if (string==null && string.equals("")){
return string;
}
4、 比较对象是否为空,使用了equals
str.equals(null)
, 合法代码示例:
1、 空指针检查应放在前面
if (a != null && a.equals(baz)){
„„
};
if (a == null ||a.equals(baz)){
„„
};
2、 已检查的对象作为调用者
if (a!=null && a.equals(method1)) { // 该处虽然对a对象进行了检查,但没有对mothod1进行检查
//whatever
}
3、 常见的判空,判非空代码编写上的错误
//判非空用了&&
if (string!=null && !string.equals("")){
return string;
}
//判空用||
if (string==null || string.equals("")){
return string;
}
4、 比较对象是否为空,使用了==
If(str==null)
3.2.16 ResultSet使用next时,需要判断是否具有记录再进行一下步操作。 , 规范描述:
java对数据库进行查询操作,取得结果集合ResultSet对象,使用next,让游标定位到下一行,下一行不存在时,next()返回false,该规则这是强制对下一行是否用记录进行判断,根据结果进行后续操作。
, PMD规则名称:
CheckResultSet
, 规则级别:
Error High
, 违规示例代码:
Statement stat = conn.createStatement(); ResultSet rst = stat.executeQuery("SELECT name FROM person");
rst.next(); // what if it returns a 'false' ? String firstName = rst.getString(1); , 合法代码示例:
// This is appropriate...
Statement stat = conn.createStatement(); ResultSet rst = stat.executeQuery("SELECT name FROM person");
if (rst.next())
{
String firstName = rst.getString(1); }
else
{
// here you deal with the error ( at least log it)
}
3.2.17 字符串使用相应的规则。
, 规范描述:
字符串是应用服务器创建最多的对象之一,对字符串操作按照合适的规则进行编写,会极大增加应用服务整体性能,以下是字符串操作相应的规则:
字符串比较需要使用equals,而不是==,~=,因为==只是对同一引用的对象比较认为相同,而不比较对象里内容是否相等;
使用StringBuffer代替string+string+string进行字符串相加,n个字符相加,如果直接用“+“号,会新产生n-1个StringBuffer对象,以及n-1个String对象,而用StringBuffer只会产生1个String,1个StringBuffer对象。
使用equalsIgnoreCase() 替代 toUpperCase/toLowerCase().equals(),这样减少一个对象的创建,效率更高。
使用StringBuffer.length()替代StringBuffer.toString().length(),这样减少一个对象的创建,效率更高。
对于String对象禁止使用string.toString(),本身是String对象,这样调用效率低下,而且由于string没有判空,很可能导致空异常的风险。 , PMD规则名称:
UseEqualsToCompareStrings
UseStringBufferLength
UnnecessaryCaseChange
UseStringBufferLen
StringToString
, 规则级别:
Error High
, 违规示例代码:
1、 字符串比较
if(str1==str2){
„„
}
2、 字符串相加
String str=str1+str2+str3+str4; 3、 大小写不敏感字符串比较
str1.toUpperCase().equals(str2.toUpperCase());
4、 取StringBuffer的长度
StringBuffer strbuf=new StringBuffer();
strbuf.append(“test1”);
strbuf.append(“test2”);
int length=strbuf.toString().length(); 5、 字符串违例转字符串
String params=request.getParameter(“test”).toString(); , 合法代码示例:
1、 字符串比较
if(str1.equals(str2)){
„„
}
2、 字符串相加
StringBuffer strbuf=new StringBuffer();
strbuf.append(str1);
strbuf.append(str2);
strbuf.append(str3);
strbuf.append(str4);
String str=strbuf.toString(); 3、 大小写不敏感字符串比较
str1. equalsIgnoreCase (str2); 4、 取StringBuffer的长度
StringBuffer strbuf=new StringBuffer();
strbuf.append(“test1”);
strbuf.append(“test2”);
int length=strbuf.length(); 5、 其他
String params=request.getParameter(“test”);
3.2.18 禁止直接调用
System.gc(),System.getRuntime().gc(),System.runFinalization()。 , 规范描述:
System.gc(),System.getRuntime().gc(),System.runFinalization()等操作会触发java虚拟机进行垃圾回收,它将暂停业务的处理,进行回收处理,如果此时应用服务器正在处理高峰器,将导致不可预测的后果。Java虚拟机自动回收机制具有很高的效率,手动方式去触发,反而导致效率降低。该规则则是禁止手动触发垃圾回收。。
, PMD规则名称:
DoNotCallGarbageCollectionExplicitly , 规则级别:
Error High
3.2.19 finalize相应的规则。
, 规范描述:
每个类的finalize是由java虚拟机垃圾回收时,由系统自动调用的方法,用于释放各类资源。对应用服务来说,对于文件,数据库等重要级别较高的系统资源,一般来说用完即释放,只有非重要性的需要手工释放的资源在finalize中释放,该规则这是针对finalize的编写制定的规范:
finalize函数override时,不能为空,或者只包含super.finalize();
不能创建与finalize函数相近的函数,例如finalize(int),系统不会自动调用该函数;
finalize函数必须含有super.finalize()语句,对父类使用的资源进行释放;
Finalize函数访问范围应为protected;
尽量避免直接调用finalize函数。
, PMD规则名称:
EmptyFinalizer
FinalizeOnlyCallsSuperFinalize
FinalizeOverLoaded
FinalizeDoesNotCallSuperFinalize
AvoidCallingFinalize
, 规则级别:
Error High
3.2.20 禁止在代码中使用System.out,ex.printStackTrace打印日志。 , 规范描述:
System.out.println,System.out.print是在屏幕中打印信息,ex.printStackTrace()是在屏幕上打印堆栈信息。屏幕上打印信息具有实时性,事后无法跟踪,这类打印日志一般在调试时使用较多,导致代码中该类命令满天飞,严重影响了代码的维护工作。
, PMD规则名称:
SystemPrintln
AvoidPrintStackTrace
, 规则级别:
rror High E
, 违规示例代码:
public int foo(String value) {
int ret=0;
System.out.println(“开始进行转整数处理”);
try {
ret= Integer.parseInt(value);
System.out.println(“成功完成转整数处理”);
} catch (Exception e) {
e.printStackTrace();
ret= 0;
}
return ret; // Very good.
}
, 合法代码示例:
public int foo(String value) {
int ret=0;
log.info(“开始进行转整数处理”);
try {
ret= Integer.parseInt(value);
log.info(“成功完成转整数处理”);
} catch (Exception e) {
Log.error(“转整数异常”,e);
ret= 0;
}
return ret; // Very good.
}
3.2.21 系统资源释放(谁创建的,谁关闭)
, 规范描述:
在java中系统资源需要手工释放,例如涉及数据库资源例如Connection,Statement,PrepareStatement,ResultSet,涉及文件资源FileOutStream,FileInStream等资源,这些资源如果在使用完后,必须在释放,否则将影响这个操作系统的运行,因此必须在finally中关闭,其原则为谁创建的,谁关闭。 , PMD规则名称:
ResourceClose
, 规则级别:
Error High
, 违规示例代码:
1、 读文件流关闭
Properties props = new Properties(); try
{
//第一种形式,可能因为异常无法关闭
FileInputStream input = new FileInputStream(CONFILENAME);
props.load(input);
//第二种形式,没有想到关闭资源
props.load(new FileInputStream(CONFILENAME)); }
catch (Exception ex)
{
throw new ConfigErrorException("读取配置文件异常"); }
2、 写文件流关闭
File file = new File(FILENAME);
try {
//第一种形式,可能因为异常无法关闭
FileOutputStream outputStream = new FileOutputStream(file);
props.save(outputStream, "test");
outputStream.close();
//第二种形式,没有想到关闭资源
props.save(new FileOutputStream(file), "test"); } catch (Exception ex) {
throw new ConfigErrorException("保存配置文件异常"); }
3、 数据库资源的关闭
// This is appropriate... Statement stat = conn.createStatement();
ResultSet rst = stat.executeQuery("SELECT name FROM person");
if (rst.next())
{
String firstName = rst.getString(1);
}
else
{
// here you deal with the error ( at least log it)
}
//可能因为异常没有关闭
rs.close();
stat.close();
conn.close();
, 合法代码示例:
1、 读文件流关闭
FileInputStream input = null;
Properties props = new Properties(); try
{
input = new FileInputStream(CONFILENAME);
props.load(input); }
catch (Exception ex) {
throw new ConfigErrorException("读取配置文件异常");
}
finally
{
if (input != null){
try
{
input.close();
}
catch (Exception ex)
{
}
}
}
2、 写文件流关闭
File file = new File(FILENAME); FileOutputStream outputStream = null; try {
outputStream = new FileOutputStream(file);
props.save(outputStream, "test"); } catch (Exception ex) {
throw new ConfigErrorException("保存配置文件异常");
} finally {
if (outputStream!= null){
try
{
outputStream.close();
}
catch (Exception ex)
{
}
}
}
3、 数据库资源释放
Connection con=null; Statement stat=null; ResultSet rs=null;
try
{
con=createConnetion();
stat = conn.createStatement();
ResultSet rst = stat.executeQuery("SELECT name FROM person");
if (rst.next()){
String firstName = rst.getString(1);
}else{
// here you deal with the error ( at least log it)
}
catch(SQLException ex) {
if(rs!=null){
try{
rs.close();
}catch(Exception ex)
{
}
}
rs =null;
if(stat!=null){
try{
stat.close();
}catch(Exception ex)
{
}
}
stat =null;;
if(conn!=null){
try{
conn.close();
}catch(Exception ex)
{
}
}
conn=null;
}
3.2.22 使用Clone时相应的规则。
, 规范描述:
复制是表示将一个对象复制成另外的对象,一般来说,复制是为了生成一个对象,该对象的内容与原对象相同,但对该对象操作不影响原对象的值,复制可分为深复制,以及浅复制,要实现深复制,由于Collection,Map等类型属性需要手工进行编程实现。以下为复制的规则:
Override Clone时,必须执行super.clone();
实现Clone方式时,需要抛出CloneNotSurportException;
所有实现Clone方法的类,必须实现Cloneable接口
, PMD规则名称:
ProperCloneImplementation
CloneThrowsCloneNotSupportedException
CloneMethodMustImplementClonable , 规则级别:
Error High
, 合法代码示例:
3.2.23 java Bean类必须实现Serialize接口。
, 规范描述:
Serialize是java bean重要的接口,其作用是将一个对象序列化成一个文件,或者网络字节序传递到网络的另外一方进行执行以及传值,对java bean进行序列化是一个良好的习惯,该规则则是对java bean序列化进行检查。
, PMD规则名称:
BeanMembersShouldSerialize
, 规则级别:
Warn High
3.2.24 比较对象相等应使用equals,而不是==。
, 规范描述:
在java中使用==是比较两个变量是否是同一个对象的引用,而不是两个对象的比较,如果要比较,则需要该类实现equals方法,实现比较的业务逻辑,采用equals进行比较。
, PMD规则名称:
CompareObjectsWithEquals
, 规则级别:
Error High
, 违规示例代码:
Integer t1=Integer.valueOf(1);
Integer t2=Integer.valueOf(1);
//该处返回值是false
System.out.println(t1==t2);
, 合法代码示例:
Integer t1=Integer.valueOf(1);
Integer t2=Integer.valueOf(1);
//该处返回值是false
System.out.println(t1.equals(t2));
3.2.25 Array数组拷贝应使用System.arrayCopy。
, 规范描述:
对于数组来说System.arrayCopy()执行效率比数组中对象依次拷贝要快很多,如果数组很大的情况下,其效率更明显。
, PMD规则名称:
, 规则级别:
Error High
, 违规示例代码:
String[] strs1={“1”,”2”, “3”,”4”};
String[] strs2=new String[4];
for(int i=0;i