Java编码规范

来源:互联网 发布:淘宝店铺手机端网址 编辑:程序博客网 时间:2024/06/05 23:00

制定本编程格式的目的是为了使软件可读性好、兼容性好、易维护等等。

注:加(*)者为重要保证要求。

一、命名规范

1.1 Package 的命名(*)

Package 的名字应由一个小写单词组成。为了保证包的唯一性,一般以公司国际域名开头。

例如:com.elanbase.db

1.2 Class 的命名(*)

Class 的名字必须由大写字母开头,并且其它单词的首写字母也要大写。

例如:DbAccess

1.3 Class 成员属性及变量的命名(*)

变量/成员属性的名字用一个小写字母开头,后面的单词以大写字母开头。

例如:private String lastName;

1.4 常量的命名(*)

Java 里的常量,是用static final 修饰的,应该用全大写加下划线命名,并且常量名应尽量指出

完整含义。如:

public static final String ORACLE_DB_DRIVER = "oracle.jdbc.driver.OracleDriver" ;

1.5 数组的命名

数组应该总是用下面的形式来命名:

byte[] buffs;

而不是:

byte buffs[];

1.6 方法的参数

和变量的命名规范一致,且应使用有意义的参数命名,如果可能的话,使用和要赋值的

属性一样的名字,如:

setCounter(int size){

this.size = size;

}

1.7 方法命名(*)

用一个小写字母开头,后面的单词以大写字母开头。应意义明确,对于属性的存取方法,

应使用getXXX()setXXX()名称,以isXXX()hasXXX()来命名返回值为boolean 类型的

方法。

1.8 一般命名注意事项

a. 用有意义的名字命名变量

首先,用完整的英语单词或约定俗成的简写命名变量,鼓励多用约定俗成的简写命名变量。

例如:

public String zipCode

public int errNo

b. 用复数命名Collection 类变量

Collection 包括数组,Vector 等。命名时使用复数:

例如:

public Collection customers

二、Java 源文件样式

Java(*.java) 源文件应遵守如下的样式规则

2.1 Class 代码布局:

package

Javadoc 注释或者其它文件头注释

类声明

Fields 声明

空行

构造函数

空行

克隆方法

空行

其它方法(不包括main)

空行

内部(Inner)类

空行

main()方法

2.2 版权信息

版权信息必须在java 文件的开头,

例如:

/**

 *

Title:编码过滤器

 *

Description: 该类实现把request请求编码为web.xml文件中所配置的字符集

 *

Copyright: Copyright (c) 2003

 *

Company: 兰贝斯信息科技

 * @author 曾小平

 * @version 1.0

 */

 

 2.3 Package/Imports(*)

package 行要在版权信息之前,中间空一行。

import classes 归类,按顺序罗列:

a. Java 标准类(java.*)

b. Java 扩充类(javax.*)

c. 第三方类

d. 你的应用程序的类

每一类空一行。

注意在第三方类里进行注释,说明它们的来源。如果import 行中包含了同一个包中的

多个类,不推荐用import pakage.* 来处理,推荐把要用的类一一import出来。这样程序

用到哪些类就可以非常清楚的看出来,有利于代码的维护,增强了代码的可读性。

例如:

import java.util.Observable;

import java.util.Date;

 

import javax.sql.Connection;

 

//Apache Xerces

import org.apache.xml.*;

import org.apache.xerces.dom.*;

 

//Application classes

import com.elanbase.db.DbAccess

 

2.4 Class Fields

类的成员变量:

/**

* Packet counters

*/

protected int[] packets;

public 的成员变量必须以生成文档(JavaDoc)的方式进行注释(/** … */)。protected

private package 定义的成员变量如果名字含义明确的话,可以没有注释。

Field 定义可遵从以下顺序:

a. public 常量

b. public 变量

c. protected 常量

d. protected 变量

e. package 常量

f. package 变量

g. private 常量

h. private 变量

2.5 存取方法(gettersetter)

接下来是类成员变量的存取的方法。

2.6 构造方法(*)

重载的构造方法应该用递增的方式写(参数多的写在后面)。

public CounterSet(){

this(10);

}

public CounterSet(int size){

this.size = size;

}

2.7 克隆方法

如果这个类是可以被克隆的,就应实现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("Unexpected CloneNotSUpportedException: " +

e.getMessage());

}

}

2.8 类方法

下面开始写类方法:

/**

* Set the packet counters

* (such as when restoring from a database)

*/

protected final void setArray(int[] r1, int[] r2, int[] r3, int[] r4)

throws IllegalArgumentException {

//

// Ensure the arrays are of equal size

//

if (r1.length != r2.length || 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);

}

2.9 toString 方法

每一个类都最好定义toString 方法:

public String toString() {

String retval = "CounterSet: ";

for (int i = 0; i < data.length(); i++) {

retval += data.bytes.toString();

retval += data.packets.toString();

}

return retval;

}

2.10 main 方法(*

如果类中包含main(String[]) 方法, 那么它应该写在类的底部。

三、代码编写风格

3.1 代码格式

代码应该用unix 的格式,而不是windows 的(比如:回车变成回车+换行)。

3.2 文档化(*)

必须遵守javadoc 风格来为源程序写注释。不仅因为它是标准,这也是被各种java

译器都认可的方法。

3.3 缩进(*)

缩进采用4 个空格2 个太少不明显,8 个太多占空间)。不要在源文件中保存Tab

字符(!!)。在使用不同的源代码管理工具时Tab 字符将因为用户设置的不同而显示为不同的

宽度。

例如:

Jbuilder7中作如下设置:

ToolsàEditor OptionsàEditor 面板上修改Block Indent4Tab Size4

3.4 行宽

行宽应该设置为80 字符。源代码一行一般不应超过这个宽度,这会导致无法完整显示。

但这一设置也可以灵活调整。超长的语句应该在一个逗号后或者一个操作符前折行。一条语

句折行后,应该根据实际情况进行缩进,总的原则是代码看起来清楚整洁。

3.5 折行(*)

需要折行时应遵循如下原则:

·在逗号后。

·在操作符前。

·高级别优先(例1)。

·第二行做两次缩进,第三行与第二行对齐。

1

longName1 = longName2 * (longName3 + longName4 - longName5)

+ 4 * longname6; // 推荐使用

longName1 = longName2 * (longName3 + longName4

- longName5) + 4 * longname6; // 避免使用

2

// 均缩进8 个空格以避免很深的缩进

private static synchronized horkingLongMethodName(int anArg,

Object anotherArg, String yetAnotherArg,

Object andStillAnother) {

// 下一层语句4 空格缩进

}

// 避免此种缩进

if ((condition1 && condition2)

|| (condition3 && condition4)

||!(condition5 && condition6)) { // 此折行方式不佳

doSomethingAboutIt(); // 此行不易读

}

// 应用此种断行/ 缩进方式

if ((condition1 && condition2)

|| (condition3 && condition4)

||!(condition5 && condition6)) {

 

doSomethingAboutIt();

}

// 或此种折行/ 缩进方式

if ((condition1 && condition2) || (condition3 && condition4)

||!(condition5 && condition6)) {

doSomethingAboutIt();

}

三重表达式可用以下缩进方式:

alpha = (aLongBooleanExpression) ? beta : gamma;

或:

alpha = (aLongBooleanExpression) ? beta

: gamma;

或:

alpha = (aLongBooleanExpression)

? beta

: gamma;

3.6 变量声明

推荐一行只写一行变量声明语句,这样有助于写注释。如:

int level; // indentation level

int size; // size of table

是推荐的,而要避免:

int level, size;

的写法。

此外,要杜绝不同类型变量写在一行的错误:

int foo, fooarray[];

 

3.7 {}

{} 中的语句应该单独作为一行,并采用如下风格:

if (i>0) {

i ++ ;

}; // 正确, { 单独作为一行

 

不推荐使用:

if (i>0) { i ++ }; // 错误, { } 在同一行

if (i>0)

{ // 错误, { ’应在上一行末尾。

i ++ ;

}

 

} 语句永远单独作为一行。

 

3.8 if else 语句(*)

多条件连续判断语句应按以下格式书写:

if ( …) {

} else if (…) {

} else {

}

应注意if 语句总应使用括号,要避免以下容易出错的写法:

if (condition) // 避免。此处略去了{}!

statement;

if (condition) statement;

 

3.9 括号

左括号和后一个字符之间不应该出现空格, 同样, 右括号和前一个字符之间也不应该出

现空格。下面的例子说明括号和空格的错误及正确使用:

CallProc( AParameter ); // 错误

CallProc(AParameter); // 正确

不要在语句中使用无意义的括号。括号只应该为达到某种目的(如语法要求或增加程序

可读性)而出现在源代码中。下面的例子说明错误和正确的用法:

if ((I) == 42) { // 错误,括号毫无意义

if ((I == 42) or (J == 42)) { // 正确,的确需要括号

3.10 语句

每行只能包括一句代码。如:

argv++; // 正确

argc--; // 正确

argv++; argc--; // 避免!

3.11 使用空格

空格应依如下规则使用:

1.关键字与括号之间应加一空格(*),如:(while 与小括号间有空格)

while (true) {

...

}

注意在方法名和左括号之间不应加空格,这样有助于区分关键字和方法调用。

2.参数列表中逗号后面应加一个空格(*)

3.操作数与操作符之间应该加一空格,除了“.”操作符和一元操作符,即“++”和“”。

(*)例:

a += c + d;

a = (a + b) / (c * d);

while (d++ = s++) {

n++;

}

printSize("size is " + foo + "/n");

4for 语句中的表达式应以空格分开(*)

for (expr1; expr2; expr3)

5.强制类型转换应加空格,如:

myMethod((byte) aNum, (Object) x);

myMethod((int) (cp + 5), ((int) (i + 3))

+ 1);

四、程序编写规范

4.1 使用方法来访问实例变量和类变量(*)

如果没有很好的理由,一般不应将实例变量或类变量设为public ,将变量设为public

的典型应用是此类代表一个“数据结构”,而不包含任何方法。

4.2 引用类变量和类方法(*)

避免使用对象引用来访问类(static)变量或类方法,而应使用类名来访问。如:

classMethod(); //OK

AClass.classMethod(); //OK

anObject.classMethod(); // 避免!

4.3 常量(*)

数字常量不应直接在编码中出现,除非是for 循环中用于计数的–10,或1

字符串常量尽量不直接在编码中出现。

4.4 ?前的逻辑运算表达式

?前的逻辑运算表达式应以括号括起,如:

(x >= 0) ? x : -x;

4.5 特殊注释

注释用XXX 表示当前是伪码,但可以工作,用FIXME 标记有问题的部分。(Use XXX in

a comment to flag something that is bogus but works. Use FIXME to flag something that

is bogus and broken.)

4.6 例外

申明的错误应该抛出一个RuntimeException 或者派生的例外。

顶层的main()函数应该截获所有的例外,并且打印(或者记录在日志中)在屏幕上。

五、编程实践问题

5.1 exit()

exit 除了在main 中可以被调用外,其他的地方不应该调用。因为这样做不给任何代

码机会来截获退出。一个类似后台服务的程序不应该因为某一个库模块决定了要退出就退

出。

5.2 垃圾收集

JAVA使用成熟的后台垃圾收集技术来代替引用计数。但是这样会导致一个问题:你必须在使用完对象的实例以后进行清场工作。

例如:

FileOutputStream fos = new FileOutputStream(projectFile) ;

project.save(fos, "IDE Project File") ;

fos.close() ;

fos =  null ;

记住!必须在使用完对象的实例以后将其关闭并且将其设置为null

 

5.3 final

绝对不要因为性能的原因将类定义为final 的(除非程序的框架要求)

如果一个类还没有准备好被继承,最好在类文档中注明,而不要将她定义为final 的。

这是因为没有人可以保证会不会由于什么原因需要继承它。

5.4 性能

在写代码的时候,从头至尾都应该考虑性能问题。这不是说时间都应该浪费在优化代码

上,而是我们时刻应该提醒自己要注意代码的效率。比如:如果没有时间来实现一个高效的

算法,那么我们应该在文档中记录下来,以便在以后有空的时候再来实现她。

不是所有的人都同意在写代码的时候应该优化性能这个观点,他们认为性能优化的问题

应该在项目的后期再去考虑,也就是在程序的轮廓已经实现了以后。应注意:

·不必要的对象构造

·不要在循环中构造和释放对象

5.5 使用StringBuffer 对象

在处理String 的时候要尽量使用StringBuffer 类,StringBuffer 类是构成String 类的

基础。String 类将StringBuffer 类封装了起来,(以花费更多时间为代价)为开发人员提供

了一个安全的接口。当我们在构造字符串的时候,我们应该用StringBuffer 来实现大部分

的工作,当工作完成后将StringBuffer 对象再转换为需要的String 对象。比如:如果有一

个字符串必须不断地在其后添加许多字符来完成构造,那么我们应该使用StringBuffer

象和她的append() 方法。如果我们用String 对象代替StringBuffer 对象的话,会花费许

多不必要的创建和释放对象的CPU 时间。

5.6 换行

如果需要换行的话,尽量用println 来代替在字符串中使用"/n"

不要这样:

System.out.print("Hello,world!/n");

要这样:

System.out.println("Hello,world!");

或者你构造一个带换行符的字符串,至少要象这样:

String newline = System.getProperty("line.separator");

System.out.println("Hello world" + newline);