- 命名规范
Java包、类的命名应尽量采用完整的英文描述符,一般采用小写英文字母,但类名、接口名以及任何非初始单词的第一个字母要大写,不能用完整英文描述的,应以该英文单词的前四个字母或能代表单词意思的缩写代替。具体如下:
- 尽量使用完整的英文描述符;
- 采用合适于相关领域的术语
- 采用大小写混合使名字可读
- 尽量少用缩写,确有需要的,要能表达其意义;
- 避免使用长的名字(小于15个字母)
- 避免使用类似的名字,或者是大小写不同的名字;
- 避免使用下划线(除静态常量等);
举例如下:
包(packge) 采用完整的英文描述符,应该都是由小写字母组成。对于全局包,将你的internet域名反转并接上包名。如:com.boyi.eim,com.boyi.oa.web
类(Class) 采用完整的英文描述符,所有单词的第一个字母大写。如:User,StuManager
接口(interface) 采用完整的英文描述符说明接口封装,所有单词第一个字母大写。名字后面加上后缀Dao,实体类实现接口加上后缀Impl
类变量:采用完整的英文描述符,第一个字母小写,后所有单词的第一个字母大写。如:userName
参数:同上
获取成员函数:封装字段,被访问时调用get set方法
普通成员函数:采用完整的英文描述符,第一个字母小写,后所有单词的第一个字母大写。
静态常量字段:全部采用大写字母,单词之间用下划线分隔。
循环计数器:通常采用字母I,j,k……………..
数组:采用完整的英文描述符,第一个字母小写,后所有单词的第一个字母大写
(二) 代码注释
良好的注释习惯对于一支程序来说,是其易于解读的关键。也就是说,如果另一个编程人员从未见过这段代码,要在合理的时间内理解代码,需要知道哪些信息。并以此作为注释的依据。因此对于注释来说,需要注意以下几点:
(1)注释应该增加代码的清晰度;
(2)保持注释的简洁;
(3)在写代码之前写注释
(4)注释出为什么做了一些事,而不仅仅是做了什么
使用代码注释的目的:
(1)文字说明代码的作用(即为什么要用编写该代码,而不是如何编写);
(2)确指出该代码的编写思路和逻辑方法;
(3)人们注意到代码中的重要转折点;
(4)使代码的阅读者不必在他们的头脑中仿真运行代码的执行方法.
代码注释原则:
1. 用文字说明代码的作用:简单的重复代码做写什么,这样的注释几乎不能给注释增加什么信息.如果你使用好的命名方法来创建直观明了的代码那么这些类型的注释绝对增加不了什么信息.
2. 如果你想违背好的编程原则,请说明为什么:有的时候你可能需要违背好的编程原则,或者使用了某些不正规的方法,.遇到这种情况时,请用内部注释来说明你在做什么和为什么要这样做。技巧性特别高的代码段,一定要加详细的注释,不要让其他开发人员花很长时间来研究一个高技巧但不易理解的程序段。
3. 用注释来说明何时可能出错和为什么出错
4. 在编写代码前进行注释:给代码加注释的方法之一是在编写一个方法前首先写上注释.如果你愿意,可以编写完整句子的注释或伪代码.一旦你用注释对代码进行了概述,就可以在注释之间编写代码.
5. 在要注释的代码前书写注释:注释一定出现在要注释的程序段前,不要在某段程序后书写对这段程序的注释,先看到注释对程序的理解会有一定帮助。如果有可能,请在注释行与上面代码间加一空行。
6. 纯色字符注释行只用于主要注释:注释中要分隔时,请使用一行空注释行来完成,不要使用纯色字符,以保持版面的整洁、清晰。
7. 避免形成注释框:用星号围成的注释框,右边的星号看起来很好,但它们给注释增加了任何信息吗?实际上这会给编写或编辑注释的人增加许多工作。
8. 增强注释的可读性,注释是供人阅读的,而不是让计算机阅读的。
1) 使用完整的语句。虽然不必将注释分成段落(最好也不要分成段落),但你应尽量将注释写成完整的句子。
2) 避免使用缩写。缩写常使注释更难阅读,人们常用不同的方法对相同的单词进行缩写,这会造成许多混乱,如果必须对词汇缩写,必须做到统一。
3) 将整个单词大写,以突出它们的重要性。若要使人们注意注释中的一个或多个单词,请全部使用大写字母。
9. 对注释进行缩进,使之与后随的语句对齐。注释通常位于它们要说明的代码的前面。为了从视觉上突出注释与它的代码之间的关系,请将注释缩进,使之与代码处于同一个层次上。
10. 为每个方法赋予一个注释标头:每个方法都应有一个注释标头。方法的注释标头可包含多个文字项,比如输入参数、返回值、原始作者、最后编辑该方法的程序员、上次修改日期、版权信息。
11. 当行尾注释用在上面这种代码段结构中时,它们会使代码更难阅读。使用多个行尾注释时(比如用于方法顶部的多个变量说明),应使它们互相对齐。这可使它们稍容易阅读一些。
12. 何时书写注释
1) 请在每个if语句的前面加上注释。
2) 在每个switch语句的前面加上注释。与if语句一样,switch语句用于评估对程序执行产生影响的表达式。
3) 在每个循环的前面加上注释。每个循环都有它的作用,许多情况下这个作用不清楚直观。
注释分类举例如下:
文档注释 在紧靠接口、类、成员函数和字段声明的前面注释它们。例如: /** 客户:客户是我们将服务和产品卖给的人或机构。*/
常规注释 常规注释去掉不再使用但你仍想保留的代码。仍想保留是因为用户万一会改变想法,或者在调试过程中想让它暂时失效。 /* 这部分代码因为已有替代代码, 于2012-10-6注释。如果一年之后还未使用,将其删除。. . . (源代码)*/
单行注释 在成员函数内采用单行注释,来说明业务逻辑、代码段和暂时变量的声明。注释符"//"后必须紧跟一个空格,然后才是注释信息。例如: // 遵照 Sarek 的规定,//于2012-10-6修改。
(三)文件样式
所有的 Java(*.java) 文件都必须遵守如下的样式规则:
(1)版权信息
版权信息或者开发者信息必须在 java 文件的开头,比如:
/** * Copyright ? 2007 Beijing Boyi software Co. Ltd. * All right reserved. */
其他不需要出现在 javadoc 的信息也可以包含在这里。
(2)包/引入(Package/Imports)
package 行要在 import 行之前,import 中标准的包名要在本地的包名之前,而且按照字母顺序排列。如果 import 行中包含了同一个包中的不同子目录,则应该用 * 来处理。举例如下:
package hotlava.net.stats;
import java.io.*;
import java.util.Observable;
import hotlava.util.Application;
这里 java.io.* 是用来代替InputStream、OutputStream 的。
(3)类(Class)
类的注释,一般是用来解释类的。例如:
/** * A class representing a set of packet and byte counters * It is observable to allow it to be watched, but only * reports changes when the current set is complete */
接下来是类定义,包含了在不同的行的 extends 和 implements
public class CounterSet extends Observable implements Cloneable{……}
(4)类成员(Class Fields)
接下来是类的成员变量:
/** * Packet counters */
protected int[] packets;
public proceted、private和 package 定义的成员变量必须添加注释。
(5)存取方法(类的设置与获取成员函数)
接下来是类变量的存取的方法。如果只是简单的用来将类的变量赋值获取值的话,可以简单的写在一行上,如类的成员变量已经有注释,类变量的存取方法可以没有注释。例如:
public int[] getPackets() {
return this.packets;
}
public void setPackets(int[] packets) { this.packets = packets; }……
要求说明的是,对于集合,加入成员函数来插入和删除项;另其它的方法不要写在一行上。
(6)构造函数
接下来是构造函数,它应该用递增的方式写(比如:参数多的写在后面)。
public CounterSet(int size){ this.size = size;}
(7)类方法(类的普通成员函数)
类的普通成员方法,举例如下:
/** * Set the packet counters
* param r1 - ……
* param r2 - ……
* ……
*/
protected final void setArray(int[] r1, int[] r2, int[] r3, int[] r4) throws IllegalArgumentException{
// Ensure the arrays are of equal size ……
}
(8)Main方法
普通类,考虑置入一个main()方法,其中包含用于测试那个类的代码,如果包含了main() 方法, 那么它应该写在类的底部。
(四)编码约定
对代码生成文档及编码的其他约定写法、习惯等,说明如下:
(1)文档化
用 javadoc 来为类生成文档。不仅因为它是标准,这也是被各种 java 编译器都认可的方法。使用 @author 标记是不被推荐的,因为代码不应该是被个人拥有的。
(2)代码缩进
缩进应该是每行2个空格。 不要在源文件中保存Tab字符, 在使用不同的源代码管理工具时Tab字符将因为用户设置的不同而扩展为不同的宽度。
(3)JSP文件命名
采用完整的英文描述说明JSP所完成的功能,尽可能包括一个生动的动词,第一个字母小写,如:viewMessage.jsp、editUser.jsp或者forumChooser.jsp等。
(4)Servlet类命名
一般对应于所服务的对象加后缀Servlet或Service来命名,如:GetFileInfoServlet,UserService等。
(五)编程建议
针对Java开发中的一些习惯,提供以下一些编程建议。
(1)多使用StringBuffer对象
在处理 String 的时候要尽量使用 StringBuffer 类,StringBuffer 类是构成 String 类的基础。String 类将 StringBuffer 类封装了起来,(以花费更多时间为代价)为开发人员提供了一个安全的接口。当我们在构造字符串的时候,我们应该用 StringBuffer 来实现大部分的工作,当工作完成后将 StringBuffer 对象再转换为需要的 String 对象。如果我们用 String 对象代替 StringBuffer 对象的话,会花费许多不必要的创建和释放对象的 CPU 时间。
(2)JSP页面标签使用
可以使用struts1自带标签,这样使项目代码具有统一性,缺点是不好升级(咱们似乎也不要求框架升级)。这里推荐大家可使用JSTL标签作为补充<c:forEach>>、<c:if>这类的标签都非常好用。
<c:if test=”${user.visitCount==1}”>
输出相应的代码
</c:if>
<c:forEach items="${finalResult.rows}" var="row">
循环内容
</c:forEach>
(3)避免使用索引来调用数据库中间层组件返回的结果集
例如以下代码:
for(int i=1; i<=dt.getRowCount(); i++){
String field1 = dt.getField(i, 0).toString(); ……
}
而应用字段名来存取结果集:
for(int i=1; i<=dt.getRowCount(); i++){
String field1 = dt.getField(i, "field1").toString(); ……
}
这样在数据库设计更改或查询的SQL语句发生变化时,不会影响到程序的执行。
(4)Java里方法返回的设计
一般我们在编写一个方法时,经常要有复杂的返回值来表示方法的处理结果。经常使用的情景是:
1. 设定返回值是boolean,方便快捷。缺点是返回过于简单,没有描述信息。
2. 设定返回值是String,可以表示多种状态的返回,缺点同1过于简单。
3. 设定返回值是xml串,可表示丰富的信息,不过还需要解析,很麻烦。Json串与之相同,需要要转换,是一个道理。
4. 设定返回值是VO对象,可表示丰富的信息,不需要解析,熟悉直接调用可使用,诸多好处。处理复杂返回情景时常用方式。
5. 方法的参数是VO对象,方法中把处理结果放入VO属性中,这样返回值就是个String或者boolean就成了,也能够完成复杂返回。这样的方式很常见,因为能够实现的比较便捷,省去麻烦。但是会造成代码可封装性不强,因为方法调用者需要点进方法内部看代码才能够明白原来需要返回的信息都放入方法传入参数的对象里了。此方法与上面方法可根据场景选择使用,如用此方法请写好注释。
6. 方法返回类型是void,自定义异常对象在方法中抛出。Extend Exception即可。可以定义属性描述异常信息和返回信息。此方法看似另类但却相当好用,依据情况不同可自定义多个Exception。调用方法时使用try catch 捕获并分别处理。具有一定的局限性,一般在处理例外业务的时候比较常见。
(5)值传递与引用传递
值传递表示方法参数是基本数据类型;引用传递表示方法参数是一个对象。
Int a = 0;
Tools.add(a) ;//方法里:a++;
System.out.println(a);
Test test = new Test(0);//对象有int属性a,初始化值为0。
Tools.add(test);//方法里:test.a++
System.out.println(test.getA());
Test test = new Test(0);//对象有int属性a,初始化值为0。
Tools.add(test);//方法里:test = new Test(1);
System.out.println(test.getA());
Test test = new Test(0);//对象有int属性a,初始化值为0。
Tools.add(test);//方法里:test = new Test(1); test.a++;
System.out.println(test.getA());
String a = “0”;
Tools.add(a);//方法里 a = “1”;
System.out.println(a);
(6)Java里的比较
'=='是用来比较两个变量(基本类型和对象类型)的值是否相等的, 如果两个变量是基
本类型的,那很容易,直接比较值就可以了。如果两个变量是对象类型的,那么它还是比较值,只是它比较的是这两个对象在栈中的引用(即地址)。
对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行
比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了,重写equals方法也要重写hashCode方法。
在定义一个类的时候,如果要实现对象的比较,也可实现Comparable接口并实现compareTo方法;
(7)数据字典处理
每个系统都有庞大的数据字典库,而很多工程师会在代码里写死这些字典的值。其实这样是不利于维护和查找的。
最好建立一个Constant类,专门处理数据字典与常量值的保存,把所有的属性值都设定为public static的。代码里任何地方的调用都可以使用Constant.属性名直接访问。尤其是一旦这些值发生突然变动,我们不至于进入代码一个个的找出来改,直接改动Constant类即可。
(8)缓存的使用规则
缓存是一把双刃剑,它的使用不能以一刀切的模式来看待。对于我们的系统,尤其是保险业务,要量体裁衣设定缓存策略。常用的缓存分为2种,一种是底层缓存,一种是业务层缓存,使用时究竟加在哪一个层级要根据实际情况定。
如果是系统的常量表,数据字典表,可作为底层缓存。
如是有一个业务结果反复被调用,并且该业务结果处理十分复杂,则可以用业务层缓存。
(9)对于系统重大的业务或技术功能要设定开关或者控制配置
凡是重大的流程或者重要的功能,最好设定一个开关或者控制的参数,如场景需要只调整这些配置即可对系统实施控制。例如对系统的缓存设定统一开关,用来控制是否使用缓存策略;对流程跳转的地方设定跳转参数,控制走向。