目 录 java
1. 序言 4 git
2. 范围 4 算法
3. 代码命名的通常原则 4 数据库
4. 代码注释的通常原则和类型 4 express
5.3. 成员方法的头部注释文档规范 6 性能优化
本规范的目的在于编写出可靠的,一致的,便于理解的JAVA源代码,而且写出的代码容易被其余人阅读,全部的JAVA代码保持良好的一致性,容易在之后的阶段中进行维护和升级。同时,也是为了经过必定时间的实践,增长软件产品的投入产出量,以提升工做效率。
在JAVA代码中,全部的代码命名的总原则是:
在JAVA代码中,咱们常常要使用代码注释的方式来帮助理解代码的含义。代码注释的通常原则主要有如下几个方面:
在JAVA代码中,常用三种类型的注释:文档型的注释,其通常格式是:以"/**"开头,以"*/"结尾; C语言类型的注释,它一般是以"/*"开头,以"*/"结尾;还有一种是一般用的单行注释的方法,即以"//"开头,对一个单行进行注释。下面以表格的方式,分别说明这三种方式在JAVA中如何更好的使用。
注释类型 |
使用方式 |
例程 |
文档型注释 |
文档型注释常常用在定义接口,类,成员方法,域的定义以前,而且这种注释能够被经过javadoc直接生成帮助文档。 |
/** Customer- A customer is any person or …… @author S.W.Ambler */ public class Customer{} |
C风格型的注释 |
当要一次对多行代码进行注释,或者这些代码将不被执行,或者对这些行进行调试时,本注释是一种比较合适的注释方法。 |
/* This code was commented .. ………… ……(the source code) */ |
单行注释 |
一般在成员方法内部注释商业逻辑,一小节代码,或者临时变量的声明。 |
//Apply a 5% discount to all //invoices over $1000 as //defined by the ….. |
同时,为了编程人员所作的文档型注释,能更有效的生成HTML格式的帮助文件,将提供如下一些更多的内容:
标志 |
使用 |
目的 |
@author authorName |
通常在类、接口定义以前的文档型注释里面使用。 |
通常是指明编写本接口或本类的做者,固然能够有多个,每个做者用@author标明。 |
@deprecated |
通常在类,成员方法定义以前的文档型注释里面使用。 |
它通常用于声明一个类或者一个成员方法被废弃,再也不使用。 |
@exception name description |
成员方法定义以前的文档型注释里面使用。 |
用于声明本成员方法将可能会抛出的异常。每个异经常使用一个@exception标明。 |
@param name description |
成员方法定义以前的文档型注释里面使用。 |
用于说明传递给该成员方法的参数,包括其类型和它的使用,每个参数用@param标明。 |
@return description |
成员方法定义以前的文档型注释里面使用。 |
用于说明本成员方法的返回值类型,若是可能,适当的描述其可能的返回值 |
@see ClassName |
通常在类,接口,成员方法,域定义以前的文档型注释里面使用。 |
用于创建一个超文本连接到指定的类,接口。通常应该详细的描述其类名。 |
@see ClassName#member functionsName |
通常在类,接口,成员方法,域定义以前的文档型注释里面使用。 |
用于创建一个超文本连接到指定的成员方法。通常应详细描述类名。 |
@version text |
通常在类,接口定义以前的文档型注释里使用。 |
用于指定相应的版本信息。 |
成员方法的命名应该采用全英文单词且是大小写混合的方式来进行。方法名的第一个单词均小写,其它单词的首字母大写。并且方法名中第一个单词最好是一个动词形式的。如:openAccount() , printMailingLabel() , save() , delete() 等。
经过这样的命名规范,很容易看出这个方法是干什么用的,它的目的是什么。尽管有时方法名会比较长,但它能很容易让其余人理解本方法的意图。
get方法,它通常返回一个属性值,通常应将get放在方法名中第一个单词的位置。而当它返回的是判断其结果是true或者false的时候,通常用"is"来取代"get"。例如:getFirstName() , getAccountNumber() , isPersistent() , isAtEnd() 等等。
经过这种命名规范,就能够很清楚的知道本方法是返回一个对象的属性或返回一个boolean值。
一样,对于set方法,它通常是用于设置对象的属性值,一样也将set放在方法名中的第一个单词的位置。如:setFirstName(String aName), setAtEnd(boolean isAtEnd), setPersistent(boolean isPersistent)等等。
构造方法通常是用来建立一个对象时要执行的初始化操做。构造方法必须具备与类名彻底一致的名字,其大小写也必须彻底一致。这种命名规范是由sun公司肯定,且必须遵照。
每个成员方法的前面必需要有相应的注释文档说明,它主要包括如下内容,但不只限于如下内容:
为了更好的描述成员方法的目的,还会在成员方法的内部给予适当的注释,通常有两种格式:/*……..*/和//……….。通常而言,内部注释文档应该说明如下一些要素:
成员方法的访问权限控制的基本原则是尽可能的限制对成员方法的访问权限。若是没有必要设置为public,则将其设置为protected,不然设置为默认方式或者private。
getXxxx方法和setXxxx方法的名称通常是: get + 属性名/ set + 属性名 或 is +属性名。 例如:
属性名 |
类型 |
get方法 |
set方法 |
FirstName |
String |
getFirstName() |
setFirstName(参数表) |
Persistent |
Boolean |
isPersistent() |
setPersistent(参数表) |
OrderItems |
Array of OrderItems Objects |
getOrderItems() |
setOrderItems(参数表) |
getXxxx方法和setXxxx方法通常对其有以下的使用方式:
// Answer the branch number, which is the leftmost four digits of the full account number
protected int getBranchNumber(){
if (branchNumber = = 0){
//The default branch number is 1000,which is the main branch in downtown Bedrock
setBranchNumber(1000);
}
return branchNumber;
}
getXxxx方法和setXxxx方法的访问权限的控制:
通常状况,将它们设置为"protected",这样,只有同包类或子类的对象能够访问它们。可是一般将getXxxx方法设置为"public"方式,而setXxxx方法则是"protected"方式。只有在极少数状况下才将setXxxx方法设置为"public"方式。固然,有时也将setXxxx方法设置为"private"方式。
属性变量的命名采用全英文单词的混合命名方式,第一个单词所有小写,之后单词的
第一个字母大写,其他小写。以便让它易于理解。而对于那些像数组或动态数组等一些多值的数据类型属性,则应该采用单词复数的方式命名(s加在最后一个单词上面),它的主要优势是能够方便的指明它们有多个值。例如: firstName, zipCode, orderItems等。
为了使对象具备更好的封闭性,通常不把属性的访问权限设置为public,建议通常把全部的属性访问权限设置为private,以防止其它类的对象直接访问本类对象的属性。而对属性的访问能够用getXxxx方法和setXxxx方法进行。
每个属性变量都要给予注释,以便其余开发人员更好的理解其含义。通常从如下几个方面给予注释:
对于组件的命名,通常采用全英文单词的命名方式,可是采用将组件类型名做为后缀的方法。这样,就很容易识别这个组件变量的目的,从它的后缀类型就能够方便的看出。也很容易在列表中找到每个组件(在不少可视化编程环境中,提供列表的方式来快速显示全部用到的组件变量)。如: okJButton, fileJMenu, newFileMenuItem等等。
常量命名采用全英文单词的方式进行,且全是大写的字母,单词之间用下划线链接。如:MINIMUM_BALANCE, DEFAULT_START_DATE等等。 它的主要优势是能够很容易的与变量区分开来。
通常而言,局部变量的命名规范遵循属性变量的命名规范,即全用英文单词命名,且除第一个单词之外,其它单词的首字母均大写。
可是,对于下面所列举的几种特殊类型的局部变量的命名有些特殊的规定:
1.streams
当一个单一的输入或输出流对象被定义和使用时,通常用in,inputStream表示输入流,而用out,outputStream表示输出流。而当一个流同时被使用为输入流和输出流的时候,则用inOut或者ioStream来命名。
2.循环计数器的使用
因为在成员方法中,咱们常常会用一些循环结构,同时也就会使用循环计数器。在之前的C,C++中,已经习惯于使用像i,j,k等变量做为循环计数器,在JAVA编码中,也采用经常使用的,单一的小写字母来命名循环计数器。例如:for(i=0;i<10;i++)
3.异常对象的命名规范
在JAVA中,常常会碰到一些例外状况的处理,通常用一个字母"e"来命名相应的例外对象,如存在多个异常则采用属性的命名方式。
局部变量的文档注释通常涉及到如下几个方面:
成员方法参数的命名规范基本上与局部变量的命名规范相同。 如: customer, inventoryItem, in , e等。
成员方法参数的文档注释:
成员方法参数的文档注释在成员方法的头部注释文档中,它应包括如下内容:
类的命名也是采用全英文单词描述的方法,但它的第一个单词的首字母必须大写,其它单词的首字母也要大写。例如: public class Customer{….} public class OrderItems{…}
类的注释文档通常位于类的定义以前,它将包含以下内容:
接口的命名,其第一个字母必须是大写的"I",以代表它是一个接口,与其它类进行区别。剩下的部分与类的命名规范同样,采用全英文单词描述的方法,第一个单词首字母大写,其它单词的首字母也大写。例如:public interface IOrderItems{……..}
public interface ICustomer{…..}
接口的文档注释必须在接口被定义前给予说明,主要包括如下内容:
3.接口内的抽象成员方法的注释,参照类的成员方法的注释。
包的命名有如下几个规则:
对于每个包,应该有一个或多个外部文档来描述这个包。通常而言,文档中应描述以下内容:
程序应以缩进形式展示程序的块结构和控制结构,在不影响展现程序结构的前提下尽量地减小缩进的层次。采用以下两种缩进方式之一:
1) |
if (expression ){ statements }else{ statements } |
一个程序的宽度若是超出页宽或屏宽,这将是很难读的,因此本规范要求使用折行缩进的方法、合并表达式或编写子程序的方法来限制程序的宽度。
1)任何一个程序最大行宽不得超过80列,超过者应折行书写。
2)建议一个函数的缩进不得超过5级,超过者应将其子块写为子函数;
3)算法或程序自己的特性有特殊要求时,能够超过5级。
性能优化的原则是先让程序运行起来,再考虑变得更快——但只有在本身必须这样作、并且经证明在某部分代码中的确存在一个性能瓶颈的时候,才应进行优化。进行优化时需使用专门的工具分析瓶颈。须要注意的是性能提高的隐含代价是本身的代码变得难于理解,并且难于维护。
对于像字符串的链接操做不使用"+"而使用专有方法 concat等其余方法,这类问题,则不能称为性能优化,而只能叫作基本常识。这类问题的解决注意不能影响程序的可读性和易维护性,如下是常见优化常识:
详见表9-1运算时间。
表 9-1 运算时间
运算 |
示例 |
标准时间 |
本地赋值 |
i=n; |
1.0 |
实例赋值 |
this.i=n; |
1.2 |
Int增值 |
i++; |
1.5 |
Byte增值 |
b++; |
2.0 |
Short增值 |
s++; |
2.0 |
Float增值 |
f++; |
2.0 |
Double增值 |
d++; |
2.0 |
空循环 |
while(true) n++; |
2.0 |
三元表达式 |
(x<0)?-x:x; |
2.2 |
算术调用 |
Math.abs(x); |
2.5 |
数组赋值 |
a[0]=n; |
2.7 |
Long增值 |
l++; |
3.5 |
方法调用 |
funct(); |
5.9 |
Throw 或者catch 违例 |
Try{throw e;} |
320 |
同步方法调用 |
synchMethod(); |
570 |
新建对象 |
new Object(); |
980 |
新建数组 |
new int[10]; |
3100 |
字串的开销:字串链接运算符"+"看似简单,但实际须要消耗大量系统资源。编译器可高效地链接字串,但变量字串却要求可观的处理器时间。该操做要建立并拆除一个StringBuffer对象以及一个String对象。
上述问题的一般解决方法是新建一个StringBuffer(字串缓冲),用append方法追加自变量,而后用toString()将结果转换回一个字串。当要追加多个字串,则可考虑直接使用一个字串缓冲——特别是能在一个循环里重复利用它的时候。经过在每次循环里禁止新建一个字串缓冲,可节省980单位的对象建立时间(见表9-1)。
更有效的解决办法是:在构造 StringBuffer 时,应该粗略的估计出它最终的总长度。默认构造函数预设了16个字符的缓存容量。append()方法首先计算字符串追加完成后的总长度,若是这个总长度大于StringBuffer的存储能力,append()方法调用私有的expandCapacity()方法。expandCapacity()方法在每次被调用时使StringBuffer存储能力加倍,并把现有的字符数组内容复制到新的存储空间。存储能力的扩展,从而致使了两次代价昂贵的复制操做。所以,咱们至少有一点能够作得比编译器更好,这就是分配一个初始存储容量大于或者等于最终字符长度StringBuffer。
所以,使用默认构造函数建立的StringBuffer在字符串链接操做上的效率其实和用"+"是同样的。若是首先估计出整个字符串最终的总长度,才会显著提升效率!
其余的字符串运算操做尽量使用 String 已经提供的方法。好比,短字符串的链接可使用 concat;子串的查找可使用 indexOf,substring 等。
一个Vector就是一个java.lang.Object实例的数组。Vector与数组类似,它的元素能够经过整数形式的索引访问。可是,Vector类型的对象在建立以后,对象的大小可以根据元素的增长或者删除而扩展、缩小。
(1)避免把新元素添加到Vector 的最前面
(2)避免从中间删除元素
(3)删除全部元素的最好方法是 removeAllElements()
(4)避免二次搜索
Vector类型的对象v包含字符串"Hello"。考虑下面的代码,它要从这个Vector中删除"Hello"字符串:
String s = "Hello";
int i = v.indexOf(s);
if(i != -1)
v.remove(s);
在这段代码中,indexOf()方法对v进行顺序搜索寻找字符串"Hello",remove(s)方法也要进行一样的顺序搜索。改进以后的版本是:
String s = "Hello";
int i = v.indexOf(s);
if(i!= -1) v.remove(i);
这个版本中咱们直接在remove()方法中给出待删除元素的精确索引位置,从而避免了第二次搜索。一个更好的版本是:
String s = "Hello";
v.remove(s);
循环内部的代码不会以任何方式修改Vector类型对象大小时,应该提早取得Vector.size()
没必要要的同步经常会形成程序性能的降低。所以,若是程序是单线程,则必定不要使用同步。
对某个方法或函数进行同步比对整个代码段进行同步的性能要好。由于代码段的同步牵涉的范围比对某个方法或函数进行同步广。
通常每一个对象都只有一个"锁",这就代表若是两个线程执行一个对象的两个不一样的同步方法时,会发生"死锁"。即便这两个方法并不共享任何资源。为了不这个问题,能够对一个对象实行"多锁"的机制。
循环的边界是指完成全部循环操做的起点和终点。若是循环体内的操做不影响边界,那么应该在循环体外,计算而且求得边界值。例如:
for(int i = 0; i < array.length; i++)
{
array[i]=i;
}
上述代码中每次循环操做,都要计算一次 array.length。
若是在循环体内用到新对象,须要在循环体开始之前构建好该对象。由标准时间表能够看出构建对象有很大的系统消耗,而且在一次循环中还要清除掉该对象,下循环再从新构建。
遍历数组、集合时,若是知足条件的元素找到,必定要使用 break 语句退出循环。