代码编程规范之所以重要是因为:
后面文中将深入讨论结构良好的程序文档的规则和要求。一个结构良好的文档应首先做到以下几点。
编写注释的目的是使你、你的开发伙伴以及后续的开发人员更好地理解你的代码。SUN公司JAVA开发组的Nagle曾说过“如果程序不值得写文档的话,意味着代码也不值得运行”。
六七十年代的COBOL语言开发着有一种注释习惯,通常用星号画一个方盒子来填写注释。这样做的确很好看,但对于最终产品来讲没有太多的益处。应当注意文档中注释和代码的比例,代码的注释应当简洁、明了。
原则上讲,我们看一段代码总能发现它在做什么。例如,下面这段代码中,我们能分析出代码的行为,但不能真正看出它的确切语义。
if ( grandTotal >= 1000.00)
{
grandTotal = grandTotal*0.95;
}
在注释文档中应说明代码所表达的语义和编码设计思想,而不应只是就事论事的讲述代码的行为。
一个JAVA源文件是由用空白行和注释分隔开的很多部分组成的,通常文件长度应该小于2000行。
每一个Java源文件都包括一个公共的类或接口。当私有类或接口与公共类相关联的时候,通常可以将其与公共类放在同一个源文件当中。公共类应是文件中的第一个类或接口。
Java源文件的组织结构如下:
所有源文件的开始部分都要有一个C语言风格的注释段,列出本程序的类名、版本信息、日期、版权声明。如下所示。
/*
* Classname
*
* Version information
*
* Date
*
* Copyright notice
*/
通常Java源文件中第一个非注释行是一个Package声明,然后是Import声明。如下所示。
package java.awt;
import java.awt.peer.CanvasPeer;
下表描述了类和接口声明中的一些部分,按照其出现顺序列出:
类和接口说明 |
说明 |
Class/Interface 文档型注释 |
/** * */ |
Class或Interface声明 |
|
Class或Interface的实现声明 |
该段注释中应该包括任何与类和接口有关的,但又不适于放在文档注释区中的注释说明 |
类静态变量 |
变量出现的顺序为,首先公共变量,然后protected变量,然后是包package一级的变量,然后是私有变量 |
变量实例 |
首先是公共变量,然后protected变量,然后是包package一级的变量,然后是私有变量 |
构造函数(Constructors) |
|
方法 |
方法应该按照功能而不是范围和可访问性来分类。例如,一个私有的类方法可以在两个公共的Instance方法的中间。这样做的目的是提高代码的可读性。 |
文档中的缩进基本单位是4个空格。Tab键应当设置为4个空格键。
代码行的长度应小于80个字符,否则不能被编辑和处理工具很好的处理。通常文档中代码例子的长度不超过70个字符。
当一个表达式因太长等原因不适于单行放置的时候,可以根据下面的规则来进行分割:
下面是一些方法调用行分割的例子
someMethod(longExpression1, longExpression2, longExpression3,
longExpression4, longExpression5);
Type var =
someMethod1(longExpression1,
someMethod2(longExpression2,longExpression3))
以上是好的格式,以下就不是很好:
Type var = someMethod1(longExpression1
someMethod2(longExpression2, longExpression3))
下面是两个算术表达式的换行分割的例子。
LongName1 =
longName2*( longName3 + longName4 – longName5)
+ 4 * longName6; // 较好的分割方式
LongName1 =
longName2*( longName3 + longName4
– longName5) + 4 * longName6; // 尽量避免这种分割方式
其中,第一方式的较好,因为换行分割点位于括号的外边,同第二种分割相比是分割的级别较高。
当方法中参数很多时,提倡如下的书写:
public void someMethod(Type longExpression1,
Type longExpression2,
Type longExpression3,
Type longExpression4,
Type longExpression5){
...
}
同样,当IF语句或其他循环语句较长时,提倡如下的书写:
if ((condition1 && condition2 )
|| (condition3 && condition4)
|| !(condition5 && condition6)) {
doSomethingAboutIt();
}
下面是3个可接受的表达式的书写方式:
alpha = (alongBooleanExpression) ? beta : gamma;
alpha = (alongBooleanExpression) ? beta
: gamma;
alpha = (alongBooleanExpression)
? beta
: gamma;
用空行将代码段按照逻辑进行分割有助于提高文件的可读性。空2行的方法应在如下情况中采用:
空1行的分割方法应该在下列情况中采用:
空格应该在下列情况下使用:
while (true) {
...
}
这样做有助于把系统保留字和方法调用区分开来,因为方法调用与其后的调用参数括号()之间是没有空格的。
a += c + d;
a = (a + b) / (c * d);
while (d++ = s++) {
n++;
}
prints(“size is ” + foo + “\n”);
for (expr1; expr2; expr3);
myMethod((byte) aNum, (Object) x);
myMethod((int) (cp + 5), ((int) (i + 3))
+ 1);
JAVA有三种注释方式。如下表所示。
注释方式 |
使用场合 |
例 子 |
文档型(Document)注 释
|
这种注释放在程序代码中的,接口函数、类、成员函数和域的声明定义之前。 文档型注释由javadoc来处理。如右图所示,为一个类创建一个外部说明文档。 |
/** Customer- A customer is any person or organization that we sell services and products to. @author S.W. Ambler */
|
C 风格的注释 |
一般来说,用C风格的注释来说明一段代码是不合适的。 这种方式主要用在维护和修改代码时,或者调试中临时关闭一段代码时使用。
|
/* This code was commented out By J.T.Kirk on Dec 9,1997 because it was replaced by the prededing code. Delete it after two years if it is still not applicable.
… … (the source code) */
|
单行注释 |
一般在成员函数的内部采用单行注释,主要用来说明事务逻辑(business logic)、代码段、临时变量的声明定义。 |
//Apply a 5% discount to all invoices //over $1000 as defined by the Sarek // generosity compaign started in // Feb. Of 1995 |
下表说明了各个部分注释的主要内容要求:
注释项 |
注释的内容 |
Arguments/parameters |
|
Fields/properties |
|
classes |
|
Compilation unite |
|
Interfaces |
|
局部变量local variables |
|
成员函数的文件注释 documentation comments |
|
成员函数的内部注释 internal comments |
|
包packages |
|
JAVA程序有两类注释:一类是实现性注释(implementation comments),另一类是文档型注释(documentation comments)。其中,Implementation 注释有C和C++两种格式,/*...*/ 和//。文档型注释是JAVA程序所独有的,在/**...*/中限定。文档型注释能够被javadoc文件工具提取到HTML文件中。
Implementation注释用于注释代码或者注释特殊的实现。文档型注释主要是描述代码段的说明,从一种非面向实现的角度来写给开发人员阅读读,这些开发人员可能手边并没有源代码。
通常注释应该是给代码一个总的描述或者提供从代码本身不太容易看出的附加性信息。注释的内容应只与读代码和理解代码有关。例如,关于相应的包(package)是如何构建,以及存放在什么目录中,不应该包括在注释中。对代码中不太明显的设计意图进行说明是应该的,但也应避免对一些明显的信息进行重复说明,尽量避免那些随着代码的维护会过时的注释。
注意:
JAVA程序段中可以有4种形式的实现注释:块注释(block)、单行注释、后注释(trailing)、行尾注释(end-of-line)。
块注释用来提供文件、方法、数据结构和算法的描述。块注释主要用在每个文件和方法的开头部分,有时也可用在方法的中间。在一个函数和方法中的块注释应该遵照缩进规则排列到说明对象的同一级深度。
通常块注释前用一个空行和其它的代码段分开。
/*
* Here is a block comment.
*/
另外,用/* - 开始的块注释能够被indent(1)识别出,作为块注释的开始。例如,
/*-
* Here is a block comment with some very special
* formatting that I want indent(1) to ignore.
*
*/
注意: 如果你自己不用indent(1),你没有必要用/* -注释开始。
单行注释应与其注释的代码处在同一缩进级别中。如果一个注释能写成单行,那么没有必要写成块注释。单行注释前面应有一个空格。例如:
if (condition) {
/* Handle the condition. */
...
}
一些非常短的注释可以加在代码的同一行内,但是应该把注释和代码分开足够大的间隔,以增加可读性。如果在一个小代码段中有多个后注释,那么应将其用TAB缩进对齐。
If (a == 2) {
Return TRUE; /* special case */
} else {
return isPrime(a); /*work only for odd a */
}
注:不提倡使用
“//”注释符能够将整行或部分行注释掉,它不能用在连续的多行文本注释中。它可以用在将小段连续的代码注释掉。所有的3种风格如下所示:
If (foo > 1){
// Do a double-flip
...
}
else{
return false; //Explain why here(不提倡使用)
}
// if (bar > 1) {
//
// // Do a triple-flip.
// ...
//}
//else{
// return false;
//}
JAVA SDK本身提供了较强的代码文档生成功能,只要代码中的注释符合一定的规则就可利用javadoc工具自动生成代码文档。Javadoc 是一种工具,它用于对一组源文件中的声明和文档注释进行语法分析,并生成一组 HTML(HyperText Markup Language,超文本标记语言)页,描述类、内部类、接口、构造函数、方法和域。文档型注释与javadoc紧密相关,可通过灵活运用文档型注释让javadoc自动生成丰富详实的代码文档。Javadoc可从*.java源文件、包说明文件、概述说明文件,以及其它文件中提取信息生成文档。
文档型注释(documentation)主要描述JAVA类、接口、构造器、方法和域。每一个文件注释的内容在/**...*/, 一个类和接口一个注释段。注释应该紧接着类声明的前面。文档型注释的格式是/**及其之后的空格都被javadoc忽略,后续行中的第一个*也被忽略。
/**
* The Example class provides ...
*/
public class Example { ...
注意:
最上一级的类和接口是不缩进的,第一行是(/**)。
其它的成员函数和构造模板要用4空格的缩进。
如果需要对类、接口进行注释但是又不适于采用文档型注释,可以用块注释或者单行注释。例如,一个类的详细实现信息可以通过在类声明后的块注释来做。文档性注释不能放在一个方法和构造之内。
源代码的文档型注释放在任何实体(类、接口、方法、属性、构造函数)的开头。
注意:
例如下面例子中的注释因为放在了import语句之前,而无法被生成文档:
/**
* This is the class comment for the class Whatever.
*/
import com.sun; // MISTAKE - Important not to put import statement here
public class Whatever {
}
注释的第一句话
每块文档型注释的第一句话应该是一个概括型语句,可简洁但完整地描述本块注释将要表达的意思。Javadoc将使用该句文字作为成员方法的概述。
注释内部的HTML标签
文档型注释遵循HTML语法规则,可以在注释中插入任何想要的HTML标签以对注释进行格式化。从注释生成的文档中缺省是没有换行的,如需要在最终文档中体现换行,需要在注释中增加换行标签:
/**
* 查询指定条件上的线路配置集。
* 该方法是静态方法,无需实例化一个本类的对象即可调用本方法。
* @param neName 网元的名字
* @param cpn 表明需要查询哪个机框、板、端口上的信息。注意本方法不按机架
* 进行查询,因为一个机架上会有两个网元,所以CPN中的rack设为-1。按从细到粗的
* 顺序,CPN中的其它字段也可设置为-1,表示查询仅精确到上一级单位。
* @return 返回AdslLineConfProfileTable对象组成的Vector。
**/
如需加粗某些文字:
/**
* This is a doc comment.
* @see java.lang.Object
*/
javadoc自身的标签
javadoc提供了若干种自定义标签,充分运用这些标签可使生成的文档结构更合理,实用性更强。Javadoc标签以@开头,且是大小写敏感的。包括以下几种标签:@author 、{@docRoot}、@deprecated、@exception、{@link}、@param、@return、@see、@serial、@serialData、@serialField、@since、@throws、@version。下面简要介绍几种很常用且比较重要的标签。
@author name-text
将代码作者的名字生成到文档中。
@param parameter-name description
描述方法的参数
@return description
描述返回值
@see reference
增加一个See Also的链接。
位置 |
标签 |
概述文档,一般是overview.html |
@see、{@link}、@since |
包文档 |
@see、{@link}、@since、@deprecated |
类和接口文档 |
@see、{@link}、@since、@deprecated、@author、@version |
属性文档 |
@see、{@link}、@since、@deprecated、@serial、@serialField |
构造函数或方法文档 |
@see、{@link}、@since、@deprecated、@param、@return、@throws (@exception)、@serialData |
尽量不要使用括号中的标签,如:@exception;因为在JDK1.2中已经用括号前面的替代了。
对于较复杂的类或方法,最好在其注释文档中增加一段如何使用本类(方法)的例子代码。由于javadoc生成的文档会忽略空格和换行,应在样例代码段前后加上
标签:/**
* A class representing a window on the screen.
* For example:
*
* Window win = new Window(parent);
* win.show();
*
*
* @author Sami Shaio
* @version %I%, %G%
* @see java.awt.BaseWindow
* @see java.awt.Button
*/
class Window extends BaseWindow {
...
}
下面给出一个简单的批处理文件用于生成javadoc文档:
del filelist.txt
dir /b /s ..\ems5100\src\*.java > filelist.txt
dir /b /s ..\emsbase\src\*.java >> filelist.txt
javadoc -windowtitle IPMS源程序文档(JavaDOC) -private @filelist.txt
另外,Javadoc 有许多有用的选项,有些相对其他更为常用。下面是实际中我们用来在 Java 平台 API 上运行 javadoc 的命令,它使用了 makefile 变量(除了未列出所有要建文档的包之外)。
javadoc -sourcepath /jdk/src/share/classes /* 源文件路径 */
-d /jdk/build/api /* 目的目录 */
-use /* 添加“用法”文件 */
-splitIndex /* 分割索引 A-Z */
-windowtitle $(WINDOWTITLE) /* 添加窗口标题 */
-doctitle $(DOCTITLE) /* 添加文档标题 */
-header $(HEADER) /* 添加运行页眉文本 */
-bottom $(BOTTOM) /* 添加底部文本 */
-group $(GROUPCORE) /* 概述页的核心标题 */
-group $(GROUPEXT) /* 概述页的扩展标题 */
-overview overview-core.html /* 概述文本 */
-J-Xmx180m /* 180MB 内存 */
java.lang java.lang.reflect /* 要建立其文档的包 */
java.util java.io java.net
java.applet
WINDOWTITLE = 'Java 平台 1.2 最终 API 规范'
DOCTITLE = 'JavaTM Platform 1.2 Final API Specification'
HEADER = 'Java Platform 1.2
Final'
提交 bug 或功能
Java 是 Sun Microsystems , Inc 在美国和其他国家的商标或注册商标。
Copyright 1993-1998 Sun Microsystems, Inc. 901 San Antonio Road,
Palo Alto, California, 94303, U.S.A.保留所有权利。'
GROUPCORE = '"核心包" "java.*:com.sun.java.*:org.omg.*"
GROUPEXT = '"扩展包" "javax.*"'
如果省略 -windowtitle 选项,则 javadoc 将文档标题复制到窗口标题。-windowtitle 选项是没有必要的,除非文档标题包含 HTML 标记。
通常JAVA代码中一行只声明一个变量:
int level; // indentation level
int size; // size of table
对比:
int level, size;
应在一个变量声明的时就对它进行初始化工作。
变量声明只应该放在代码段的开始部分。代码段是指花括号{}所包括的区域。严禁到使用时才声明变量。
void myMethod(){
int int1 = 0; //beginning of method block
if (condition) {
int int2 = 0; // beginning of “if” block
...
}
}
唯一的例外是for循环中的循环变量,如
for (int i = 0; i < maxLoops; i++){ ... }
为了避免局部变量被高一级的变量所覆盖,应避免在局部代码块中采用同样的变量名称。例如,
int count;
...
myMethod() {
if (condition) {
int count; // 应避免这种情况
...
}
...
}
当编写JAVA的类和接口是应该遵循下列格式规则:
class Sample extends Object {
int ivar1;
int ivar2;
Sample(int i, int j) {
ivar1 = i;
ivar2 = j;
}
// 空行
int emptyMethod()
};
每一行应该只包括一个语句,例如:
argv++; //正确
argc++; //正确
argv++; argc--; //错误
复合语句是指用一对花括号包围起来的任意数量的简单语句{语句}。
带值的返回语句不需要用圆括号,除非有时不得不用括号使返回结构更加明显。例如:
return;
return myDisk.size( );
return (size ? size : defaultSize);
if-else类语句有如下几种形式:
if (condition) {
statements;
}
if (condition) {
statements;
} else {
statements;
}
if (condition) {
statements;
} else if (condition) {
statements;
} else {
statements;
}
注意:if语句一定要用花括号{};要避免以下混淆形式:
if (condition) //要避免这种对花括号的忽略!
statement;
for语句形式如下:
for (initialization; condition; update) {
statements;
}
一个空的for循环语句的形式如下:
for (initianlization; condition; update);
当for循环的initianlization部分和update部分中有多个用逗号隔开的变量时,通常变量的数量不应该超过3个。如果必要的话,可以在for循环的之前(initianlization部分前)或者在循环的尾部(update部分)使用单独的语句来说明。
一个while语句结构如下:
while (condition) {
tatements;
}
下面是一个空的while循环语句:
while (condition);
一个do-while 循环语句的形式如下:
do {
statements;
} while (condition);
一个switch语句的结构如下:
switch (conditon) {
case ABC:
statements;
/* falls through */
case DEF:
statements;
break;
case XYZ:
statements;
break;
default:
statements;
break;
}
每一个switch语句中应该包括一个default case语句。
try-catch语句有以下格式:
try {
statements;
} catch (ExceptionClass e) {
statements;
}
try-catch语句也可以跟随finally,它总是被执行,而不受异常是否抛出的影响。
try {
statements;
} catch (ExceptionClass e) {
statements;
} finally {
statements;
}
命名规范的目的是提高程序的可读性,使程序易于理解。
基本命名原则:
较好的命名应该象firstName、grandTotal、CorporateCustomer, 而诸如x1、y1等命名反映任何命名含义,而且造成代码难以理解、维护和改进。
如果软件开发人员应注意软件用户的一些约定术语,不应当随意的创造术语。这会降低软件的易用性。
一般情况下应该用小写字母来命名,其中类(class)和接口(interface)名称的首字母用大写。
设计命名中应该慎用缩写命名。如要采用,则应采用统一的缩略规则,并且在文中的相应部分统一采用缩写。例如,采用num作为number的缩写,那么在整个文档中应该始终使用该缩写。
命名的长度应小于15个字母(但是可以使用更长的形式,以便更好的表达意思)。
命名时应避免采用几乎相同的名称。例如,变量名称persistentObject和persistentObjects不应当同时运用;anSqlDatabase和anSQLDatabase也不应同时使用。
有时名称中会含有固定的缩略词,例如SQL代表Standard Query Language. 而在命名时sqlDatabase和SqlDatabase就比sQLDatabase和SQLDatabase易于阅读。
成员函数名称应采用完整的英文单词组成,除第一个单词外其余的成员单词的首字母用大写。成员函数取名采用动宾结构,名称中的第一个词为动词。例如,
openAccount();
printMailingLabel();
save();
delete();
成员函数的命名应能够准确、简洁地表示其功能。虽然函数名稍微有点长,但还是值得的,因为它能够增加代码的可读性。
对(fields/property)赋值的访问性函数,通常的命名方式是用get/set+“访问对象名”。当对象为布尔型时,用is+“访问对象名”构成,其中对象名称用大小写混合的方式,首字母大写。这些命名约定是JDK标准和JAVA Beans开发时所要求的。
get型函数
Get型函数返回一个域(field)的值。在命名时将“get”作为第一个单词;如果是boolean型的域,那么将“is”作为函数名称的第一个单词。如:
getFirstName();
getAccountNumber();
getLostEh();
isPersistent();
isAtEnd();
set型函数
这些函数主要用来对一个域(field)来赋值,命名时将“set”作为第一个单词。如:
setFirstName(string aName);
setAccountNumber(int anAccountNumber);
setReasonableGoals(Vector newGoals);
setAtEnd(boolean isAtEnd);
构造函数Constructor
构造函数是成员函数的一种,当一个对象初次创建的时候负责对象初始化工作。构造函数的名称总是与其创建的类完全相同。如:
Customer();
SavingAccount();
PresistenceBroker();
通常应该用完整的英文单词来命名一个域,使其名称能够很好的反映其代表的值。如:
firstName;
zipCode;
unitPrice;
discountRate;
orderItems;
组件接口的命名应该采用全英文单词,后缀为该组件的类型,如botton、list等。命名应能够较好表达该组件的用途,并使得该组件易于在applet或application中查找。组件应避免取诸如botton1、botton2等抽象的名称。如:
okButton;
customerList;
fileMenu;
newFileMenuItem;
常量的命名常用全英文单词来说明,所有的字母采用大写方式,单词之间用下划线连接。
如:
MINMUM_BALANCE;
MAX_VALUE;
DEFAULT_START_DATE;
数组(array)和vector的命名方法是,用array和vector所存对象名称的复数表示,名称为全英文单词组成,非开头单词的首字母采用大写。例如,
customers;
orderItems;
aliases;
局部变量的命名规范与前面提到的field命名原则类似,命名用全英文单词,其中非开头单词的首字母大写。
当在一个成员函数中打开一个输入输出流的时候,SUN公司的命名约定如下:
命名用in +“流名称”;
命名用out +“流名称”;
命名用inOut +“流名称”;
循环变量的命名一般用i、j、k来表示,也可以用更有意义的单词来表示。对于嵌套循环,一般外层循环用i, 第二层用j, 依此类推。
异常处理在JAVA代码编程中是十分常用的。通常用小写ex 来作异常对象(exception objection)的对象。例如,
public LocaLize(String FileName) {
try {
filename = FileName;
jbInit();
}
catch(Exception ex) {
ex.printStackTrace();
}
}
下表是SUN公司的一些通用变量和对象的JAVA命名约定。
变量类型 |
命名前缀 |
offset |
Off |
length |
Len |
byte |
B |
char |
C |
double |
D |
float |
F |
long |
L |
Object |
O |
String |
S |
Arbitrary value |
V |
下表总结了类、接口、包的命名规则。
定义类型 |
命名规则 |
例子 |
Packages |
包名称的前缀总是用小写的ASCII字母来表示的,并且总是采用一级域名,如com,edu,gov,mil.net,ort,或者是ISO 3166标准中规定的国家名的2字母缩写。 一个包名称后面的组件名根据一个组织的各个名称约定来取。
|
com.sun.eng com.apple.quicktime.v2 edu.cmu.cs.bovik.cheese com.zte.resmaster.util |
Class |
类名称应该是名词,且其内部的每一个词的首字母应大写。类名应简单而有意义。组成类名的单词不应用缩写。除非这些缩写已被广泛理解,如URL和HTML。 类名尽量使用名词,或者名词+动词的形式。 |
Class Raster; Class ImageSprite; |
Inerfaces |
接口名称的大写规则与类名相同。 接口名尽量使用形容词,如:Runnable。或者名词,并且名词最好是带er,如:RequestHandler。 |
Interface RasterDelegate interface Sroring |
Methods |
方法的取名应该是动词。它是大小写混合的。成员单词的首字母小写,且中间单词的首字母大写 |
Run(); RunFast(); GetBackground( |
Variables |
除了变量外,所有的instance,calss,和类常量是大小写混合的。成员单词的首字母小写,且中间单词的首字母大写。另外,变量名称不应该用下划线“_”和“$”符号开始。
变量名称应该简短但有意义。除非是临时使用的变量外,不应当用单个单词来命名变量。
通常临时变量命名时,i,j, k,m,n,来表示整型变量;c,d,e表示字符型变量
|
Int i; Char c; Float myWidth; |
Constants |
所有的常量名称应该用大写字母表示,各个成员单词之间用下划线“_”相连接。
|
Static final int MIN_WIDTH = 4;
Static final int MAX_WIDTH = 999 Static final int GET_THE_CPU = 1; |
在开发J2EE系统的过程中,随着系统开发的深入,如何控制各种对象和资源的命名就成为一个使系统成功的一个重要因素。任何随意性都将导致系统在后期产生混乱,结构不清晰,导致更多的维护成本。
实体Bean
Bean :com.company.projectname.subsystem.ejbname.ejb.EjbnameEJB
Remote :com.company.projectname.subsystem.ejbname.ejb.EjbnameRemote
Home :com.company.projectname.subsystem.ejbname.ejb.EjbnameHome
例如:用户对象
Bean : com.zte.resmaster.sysmanage.user.ejb.UserEJB
Remote : com.zte.resmaster.sysmanage.user.ejb.UserRemote
Home : com.zte.resmaster.sysmanage.user.ejb.UserHome
会话Bean
Bean : com.company.project.subsystem.ejbname.manager.EjbnameEJB
Remote : com.company.project.subsystem.ejbname.manager.EjbnameRemote
Home : com.company.project.subsystem.ejbname.manager.EjbnameHome
例如:用户对象
Bean : com.zte.resmaster.sysmanage.user.manager.UserEJB
Remote : com.zte.resmaster.sysmanage.user.manager.UserRemote
Home : com.zte.resmaster.sysmanage.user.manager.UserHome
数据值对象(Data Value设计模式中采用)
com.company.projectname.subsystem.ejbname.model.EjbnameModel
例如:用户对象
com.zte.resmaster.sysmanage.user.model.UserModel
DAO对象
DAO接口:com.company.projectname.subsystem.ejbname.dao.EjbnameDAO
DAO实现:com.company.projectname.subsystem.ejbname.dao.EjbnameDAOImpl
DAO数据库实现:
com.company.projectname.subsystem.ejbname.dao.EjbnameDAODatabase
DAO工厂:com.company.projectname.subsystem.ejbname.dao.EjbnameDAOFactory
例如:用户对象
DAO接口:com.zte.resmaster.sysmanage.user.dao.UserDAO
DAO实现:com.zte.resmaster.sysmanage.user.dao.UserDAOImpl
DAOOracle实现:com.zte.resmaster.sysmanage.user.dao.UserDAOOracle
DAOSybase实现:com.zte.resmaster.sysmanage.user.dao.UserDAOSybase
DAO工厂:com.zte.resmaster.sysmanage.user.dao.UserDAOFactory
异常
com.company.projectname.subsystem.ejbname.exceptions.XXXException
例如:用户关键字已经存在的异常
com.zte.resmaster.sysmanage.user.exceptions.UserDupKeyException
工具类
com.company.projectname.subsystem.ejbname.util.Xxxx
例如:
com.zte.resmaster.sysmanage.user.util.UserEJBHelper
Servlet类
com.company.projectname.subsystem.web.XxxServlet
例如:数据网子系统
com.zte.resmaster.datanet.web.MainServlet
Handler处理类
com.company.projectname.subsystem.web.handlers.ObjectHandler
例如:线路对象
com.zte.resmaster.datanet.web.handlers.LineHandler
Web工具类
com.company.projectname.subsystem.util.XXX
例如:
com.zte.resmaster.datanet.util.DataUtil
Web异常类
com.company.projectname.subsystem.exceptions.XXXException
例如:通用错误类
com.zte.resmaster.datanet.exceptions.GeneralFailureException
数据
com.company.projectname.util.data.XXX
例如:
com.zte.resmaster.util.data.SystemProperties
跟踪调试
com.company.projectname.util.tracer.XXX
例如:
com.zte.resmaster.util.trace.Debug
UI(用户界面)
com.company.projectname.util.ui.XXX
例如:字体选择面板
com.zte.resmaster.util.ui.FontChooserPanel
Theme(界面样式)
com.company.projectname.util.theme.XXX
例如:IzPack的菜单UI样式
com.zte.resmaster.util.theme.IzPackMenuUI
EJB注册(可以不用projectname)
Ejb/projectname/ejbtype/EjbnameEJB
例如:
ejb/resmaster/entity/UserEJB
ejb/resmaster/session/SecurityEJB
还可以加入子系统名称,以便管理。如:
ejb/resmaster/baseres/session/QuyuEJB。
可以把ejbtype去掉,如:
ejb/resmaster/baseres/QuyuEJB。
引用EJB
ejb/EjbnameEJB
例如:
ejb/UserEJB
引用数据源(可以使用DatabaseType)
jdbc/DatabaseType/DataSources
例如:jdbc/oracle/ResTxDataSource
一般不要随意的将变量和实例的访问属性设置为public。
不要用一个对象去直接访问类变量或者方法,而是应该用它的类名。例如,
classMethod(); //OK
Aclass.classMethod(); //OK
AnObject.classMethod(); //避免采用
编码中不应直接使用数字常量,除了在for循环中用的-1,0,1等计数常量。
数字常量又叫Magic Sum,有时你自己都不知道它的值究竟是什么。
避免在一条语句中将一个数值赋给多个变量,这样不易阅读。例如,
fooBar.fChar = barFoo.lchar = ‘c’; //应当避免
不要在语句中容易和“相等”混淆的地方放置操作符。例如,
if (c++ = d++) { //JAVA不允许的
...
}
应当改为,
if ((c++ = d++) != 0) {
...
}
要警惕IF判断语句中的赋值,上面的形式Java编译器拒绝,但是下面的接受:
boolean flag = false;
if (flag = booleanexpression){
...
}
所以,你要清楚你究竟要干什么,不清楚时,写成多行语句。
另外,不要把一个语句嵌入在另外一个语句中。例如,
d = (a = b + c) + r // 避免使用
应该写成,
a = b + c;
d = a + r;
由于Java中有内存垃圾收集的机制,并且没有指针类型,开发者就可以从C/C++的内存噩梦中解脱出来。正因为如此,很多开发者就不再关注内存的使用问题。小心,这里存在陷阱。
请注意,Java的这个机制是内存垃圾收集而非内存收集!所以,你需要把使用的对象变成JVM可以识别的垃圾。一般而言,在方法中声明使用的变量在方法外面时就会成为垃圾。但是有些却不是,例如:
private HashMap dialogMap = new HashMap();
...
{
JDialog dialog = new JDialog(“XXX”);
...
dialogMap.put(dialog.getTitle(),dialog);
}
...
如果你在整个代码期间都没有调用如下语句:
Object ref =dialogMap.remove(key);
...(释放资源,如:((JDialog)ref).dispose())
ref = null;
或者
dialogMap.clear()(有时,仅仅这个语句还不行)
那么你的代码就存在内存泄漏问题!
几乎所有存储对象的结构都要引起注意,看看是否有资源没有释放,没有成为垃圾而无法回收。下面的对象要严格释放:
java.sql.Connection;
java.sql.Statement;
java.sql.PreparedStatement
java.sql.CallableStatement
java.sql.ResultSet
这些对象如果不释放其资源,不仅仅是内存问题;还将引起数据库问题。如果不释放Connection,那么很快就用尽连接或是数据库巨慢(数据库连接数目还受到Licence的限制)。如果不释放后面的对象资源,那么很快就会用尽数据库游标,因为每打开一次后面的资源就要使用一个游标,即使语句中没有使用游标(其实每个DDL语句都使用一个缺省游标)。而数据库的游标一般是有限制的,Oracle8.1.6中缺省为100,Oracle8.1.7中缺省为300。
千万注意!
可能在一段时间内永远不会碰到内存不足的问题,是不是就不用警惕上面提到的内容呢?
不!
JVM中垃圾内存的收集还受到内存容量的影响。当还有可用内存时,常常不会主动去垃圾收集。这就是为什么常常没有碰到内存不足的问题,因为你机器的内存足够大(256M)。
为了Java程序有序的运行,你可以为它设定一个最大最小内存使用量。就像Weblogic中的一样,如:
-hotspot -ms64m -mx64m。
这样有利于更好的利用垃圾收集机制。
妨碍程序国际化的一个常见的设计失误是:把在界面上显示的内容在源代码中进行硬编码,这使得了application或者applet不能被很方便地进行本地化处理。
为了解决这个问题,可以在完成代码的编写和测试以后,把用户界面中的硬编码字符串进行资源化处理,另外的一个较好办法是,在界面设计过程中就对可视的字符串进行资源化处理。
如果使用Jbuilder,就可以使用它所提供的两种方法来完成工作,这两种方法分别是:资源字符串向导(Resource Strings wizard)和本地化属性设置对话框(Localizable Property Setting dialog box)。
如果不使用Jbuilder工具,也可以模仿它所生成的代码,自己进行相应处理。
Resource Strings wizard能够快速、方便地扫描源代码,把硬编码的字符串放到Java的ResourceBundle类中。
该向导不仅能够处理Jbulider生成的源文件,对于其它来源的Java文件也能处理。
ResourceBundles资源包,是包含有可翻译字符串集合的特殊的文件,
ResourceBundle有两种:PropertyResourceBundle和ListResourceBundle。
PropertyResourceBundles是带有.properties扩展名的文本文件,和源代码生成的class文件在一个目录下。
对于PropertyResourceBundles,在对应用程序的资源包进行修改或者添加时,无需重新编译。
而ListResourceBundles 是以Java源代码文件形式存在的。 由于是以Java源码形式实现的,所以任何新建或者修改的ListResourceBundles,都需要被重新编译才能发布。与PropertyResourceBundles相比,ListResourceBundles的效率要高的多,所以Jbuilder把其作为缺省都选择。
该属性设置框允许你在创建或者定制用户界面的组件时,就可对可视化的字符串进行资源化处理。
在对象查看器中,右键单击任何text属性字段(比如按钮控件的标签属性)。
然后选择ResourceBundle命令,显示本地化属性设置对话框。
该对话框显示的属性和资源字符串向导对话框中的类似,只是含有影响单个选定对象属性的选项。
在对象查看器中进行资源化处理非常地快速和方便,你完全可以把这个过程看成是对应用程序地组件进行定制的完整步骤之一。
使用Unicode escape序列的16进制值来插入Unicode字符,另外,要用尖括号将其括起来。
比如,要把中文的字符“确定”作为按钮的标签,就可以输入<\u786e\u5b9a>。
当设计一个将要被本地化为多种语言的用户界面时,最为重要的一个规则是:一定要使用动态布局管理器(dynamic layout manager)。
这可以解决诸如让按钮大小随着它的标签文字的宽度而自动变化等问题。
在实际设计界面时,需要综合考虑、使用Java平台提供的五种最常使用的布局管理方式:BorderLayout, GridLayout ,FlowLayout ,BoxLayout和 GridBagLayout。
编译器对使用本地编码(或者叫本地代码页)的源代码进行编译,这种源码的存储格式被绝大多数的文本编辑器所使用。
编译器会自动根据操作系统环境选择合适的本地代码。也可以为由不同的本地代码写成的源代码文件指定任意的JDK编码。
指定编码的名称,就可以控制编译器解释处理ASCII字符集以外的那些字符。这可以在工程项目范围一级进行指定,也可以在命令行用encoding编译选项来进行控制。如果该选择没有被指定,则会使用平台缺省的本地代码转换器。
除了最简单的关于界面显示语言的国际化,还要保证自己的程序对于其它国家相关的特性提供支持,实际应用中的情况是非常复杂的。
其它一些需要考虑的因素包括:提示信息,GUI组件上的标签,在线帮助,声音,颜色,图形,图标,日期,货币符号,数字,小数值,分隔符。。。。。。
此外,一些具体处理过程和方式也会不同,例如排序方法,输入处理等。
这些可以利用java.text包以及java.util包中的TimeZone、SimpleTimeZone和Calendar等类进行辅助处理。
通常建议在有多个操作符的表达式中借助于括号来更加清楚地表达一条语句。这能帮助你和其他程序员更好的理解代码。
if (a == b && c == d) // 避免
if ((a == b) && (c == d)) // 较好
写代码时应该尽量让你的程序结构很好地体现意图。如:
if (booleanExpression) {
return true;
} else (
return false;
)
应该改为如下语句。
Return booleanExpression;
类似的,
if (condition) {
return x;
}
return y;
应该写为,
return (condition ? x : y);
如果在三重操作符“?:”中的“?”前面还有二元操作,那么必须采用括号。如,
(x >= 0) ? x : -x;