??xml version="1.0" encoding="utf-8" standalone="yes"?>
虽然|上商店形式多样,每个站点有自q特色,但也有其一般的共?单就"商品的变?以便?qing)时通知订户"q一?是很多网上商店共有的模式,q一模式cMObserver patern.
具体的说,如果|上商店中商品在名称 h{方面有变化,如果pȝ能自动通知?x)?是|上商店区别传统商店的一大特?q就需要在商品product中加入Observerq样角色,以便productl节发生变化?Observer能自动观察到q种变化,q能q行?qing)时的update或notify动作.
Java的APIqؓ(f)为我们提供现成的Observer接口Java.util.Observer.我们只要直接使用它就可以.
我们必须extends Java.util.Observer才能真正使用?
1.提供Add/Delete observer的方?
2.提供通知(notisfy) 所有observer的方?
import java.util.Observable; public class product extends Observable { private String name; private float price; public String getName() { public void setName(String name) { } public float getPrice() { public void setPrice(float price) { } //以下可以是数据库更新 插入命o(h). } public static void main(String[] args) { |
我们注意?在productcM 的setXXXҎ(gu)?我们讄?notify(通知)Ҏ(gu), 当调用setXXX,实际上就触发了notisfyObserversҎ(gu),q将通知相应观察者应该采取行动了.
下面看看q些观察者的代码,他们I竟采取了什么行?
//观察者NameObserver主要用来对品名U?name)q行观察?br>public class NameObserver implements Observer{ private String name=null; public void update(Observable obj,Object arg){ name=(String)arg; } } } //观察者PriceObserver主要用来对品h(hun)?price)q行观察?br>public class PriceObserver implements Observer{ private float price=0; public void update(Observable obj,Object arg){ price=((Float)arg).floatValue(); } } } |
1.1 Z么要有编码规?Why Have Code Conventions)
~码规范对于E序员而言ؓ(f)重要Q有以下几个原因Q?/p>
- 一个Y件的生命周期中,80%的花费在于维?br>- 几乎没有M一个YӞ在其整个生命周期中,均由最初的开发h员来l护
- ~码规范可以改善软g的可L,可以让程序员快而彻底地理解新的代码
- 如果你将源码作ؓ(f)产品发布Q就需要确d是否被很好的打包q且清晰无误Q一如你已构建的其它M产品
Z执行规范Q每个Y件开发h员必M致遵守编码规范。每个h?/p>
本文档反映的是Sun MicroSystems公司QJava语言规范中的~码标准部分。主要A(ch)献者包括:(x)Peter KingQPatrick NaughtonQMike DeMoneyQJonni KanervaQKathy Walrath以及(qing)Scott Hommel?/p>
本文档现由Scott Hommell护Q有兌论意见请发至shommel@eng.sun.com
q部分列Z常用的文件名?qing)其后缀?/p>
JavaE序使用下列文g后缀Q?/p>
文gcd | 文g后缀 |
Java源文?/td> | .java |
Java字节码文?/td> | .class |
常用的文件名包括Q?/p>
文g?/td> | 用?/td> |
GNUmakefile | makefiles的首选文件名。我们采用gnumake来创建(buildQY件?/td> |
README | 概述特定目录下所含内容的文g的首选文件名 |
一个文件由被空行分割而成的段落以?qing)标识每个段落的可选注释共同组成。超q?000行的E序难以阅读Q应该尽量避免?Java源文件范?提供了一个布局合理的JavaE序范例?/p>
3.1 Java源文?Java Source Files)
每个Java源文仉包含一个单一的公q或接口。若U有cd接口与一个公q相关联,可以它们和公共cL入同一个源文g。公q必须是这个文件中的第一个类或接口?/p>
Java源文件还遵@以下规则Q?/p>
- 开头注释(参见"开头注?/font>"Q?br>- 包和引入语句Q参?包和引入语句"Q?br>- cd接口声明Q参?cd接口声明"Q?
所有的源文仉应该在开头有一个C语言风格的注释,其中列出cd、版本信息、日期和版权声明Q?/p>
/* * Classname * * Version information * * Date * * Copyright notice */
3.1.2 包和引入语句(Package and Import Statements)
在多数Java源文件中Q第一个非注释行是包语句。在它之后可以跟引入语句。例如:(x)
package java.awt; import java.awt.peer.CanvasPeer;
3.1.3 cd接口声明(Class and Interface Declarations)
下表描述了类和接口声明的各个部分以及(qing)它们出现的先后次序。参?Java源文件范?/font>"中一个包含注释的例子?/p>
c?接口声明的各部分 | 注解 | |
1 | c?接口文档注释(/**……*/) | 该注释中所需包含的信息,参见"文档注释" |
2 | cL接口的声?/td> | |
3 | c?接口实现的注?/*……*/)如果有必要的?/td> | 该注释应包含M有关整个cL接口的信息,而这些信息又不适合作ؓ(f)c?接口文档注释?/td> |
4 | cȝ(静?变量 | 首先是类的公共变量,随后是保护变量,再后是包一U别的变?没有讉K修饰W,access modifier)Q最后是U有变量?/td> |
5 | 实例变量 | 首先是公q别的Q随后是保护U别的,再后是包一U别?没有讉K修饰W?Q最后是U有U别的?/td> |
6 | 构造器 | |
7 | Ҏ(gu) | q些Ҏ(gu)应该按功能,而非作用域或讉K权限Q分l。例如,一个私有的cL法可以置于两个公有的实例Ҏ(gu)之间。其目的是ؓ(f)了更便于阅读和理解代码?/td> |
4个空格常被作为羃q排版的一个单位。羃q的切解释q未详细指定(I格 vs. 制表W?。一个制表符{于8个空?而非4??/p>
量避免一行的长度过80个字W,因ؓ(f)很多l端和工具不能很好处理之?/p>
注意Q用于文档中的例子应该用更短的行长Q长度一般不过70个字W?/p>
当一个表辑ּ无法容纳在一行内Ӟ可以依据如下一般规则断开之:(x)
- 在一个逗号后面断开
- 在一个操作符前面断开
- 宁可选择较高U别(higher-level)的断开Q而非较低U别(lower-level)的断开
- 新的一行应该与上一行同一U别表达式的开头处寚w
- 如果以上规则D你的代码混ؕ或者你的代码都堆挤在双Q那׃之以~进8个空根{?
以下是断开Ҏ(gu)调用的一些例子:(x)
someMethod(longExpression1, longExpression2, longExpression3, longExpression4, longExpression5); var = someMethod1(longExpression1, someMethod2(longExpression2, longExpression3));
以下是两个断开术表达式的例子。前者更好,因ؓ(f)断开处位于括可辑ּ的外边,q是个较高别的断开?/p>
longName1 = longName2 * (longName3 + longName4 - longName5) + 4 * longname6; //PREFFER longName1 = longName2 * (longName3 + longName4 - longName5) + 4 * longname6; //AVOID
以下是两个羃q方法声明的例子。前者是常规情Ş。后者若使用常规的羃q方式将?x)ɽW二行和W三行移得很靠右Q所以代之以~进8个空?/p>
//CONVENTIONAL INDENTATION someMethod(int anArg, Object anotherArg, String yetAnotherArg, Object andStillAnother) { ... } //INDENT 8 SPACES TO AVOID VERY DEEP INDENTS private static synchronized horkingLongMethodName(int anArg, Object anotherArg, String yetAnotherArg, Object andStillAnother) { ... }
if语句的换行通常使用8个空格的规则Q因为常规羃q?4个空??x)语句体看h比较费劲。比如:(x)
//DON’T USE THIS INDENTATION if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { //BAD WRAPS doSomethingAboutIt(); //MAKE THIS LINE EASY TO MISS } //USE THIS INDENTATION INSTEAD if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { doSomethingAboutIt(); } //OR USE THIS if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { doSomethingAboutIt(); }
q里有三U可行的Ҏ(gu)用于处理三元q算表达式:(x)
alpha = (aLongBooleanExpression) ? beta : gamma; alpha = (aLongBooleanExpression) ? beta : gamma; alpha = (aLongBooleanExpression) ? beta : gamma;
JavaE序有两cL释:(x)实现注释(implementation comments)和文档注?document comments)。实现注释是那些在C++中见q的Q?*...*/?/界定的注释。文档注?被称?doc comments")是Java独有的,q由/**...*/界定。文档注释可以通过javadoc工具转换成HTML文g?/p>
实现注释用以注释代码或者实现细节。文档注释从实现自由(implementation-free)的角度描qC码的规范。它可以被那些手头没有源码的开发h员读懂?/p>
注释应被用来l出代码的LQƈ提供代码自n没有提供的附加信息。注释应该仅包含与阅d理解E序有关的信息。例如,相应的包如何被徏立或位于哪个目录下之cȝ信息不应包括在注释中?/p>
在注释里Q对设计决策中重要的或者不是显而易见的地方q行说明是可以的Q但应避免提供代码中己清晰表辑և来的重复信息。多余的的注释很Ҏ(gu)q时。通常应避免那些代码更新就可能q时的注释?/p>
注意Q频J的注释有时反映Z码的低质量。当你觉得被q要加注释的时候,考虑一下重写代码其更清晰?/p>
注释不应写在用星h其他字符d来的大框里。注释不应包括诸如制表符和回退W之cȝҎ(gu)字符?/p>
5.1 实现注释的格?Implementation Comment Formats)
E序可以?U实现注释的风格Q块(block)、单?single-line)、尾?trailing)和行?end-of-line)?/p>
块注释通常用于提供Ҏ(gu)ӞҎ(gu)Q数据结构和法的描q。块注释被置于每个文件的开始处以及(qing)每个Ҏ(gu)之前。它们也可以被用于其他地方,比如Ҏ(gu)内部。在功能和方法内部的块注释应该和它们所描述的代码具有一L(fng)~进格式?/p>
块注释之首应该有一个空行,用于把块注释和代码分割开来,比如Q?/p>
/* * Here is a block comment. */
块注释可以以/*-开_(d)q样indent(1)可以将之识别ؓ(f)一个代码块的开始,而不?x)重排它?/p>
/*- * Here is a block comment with some very special * formatting that I want indent(1) to ignore. * * one * two * three */
注意Q如果你不用indent(1)Q就不必在代码中使用/*-Q或Z人可能对你的代码q行indent(1)作让步?/p>
参见"文档注释"
5.1.2 单行注释(Single-Line Comments)
短注释可以显C在一行内Qƈ与其后的代码h一L(fng)~进层。如果一个注释不能在一行内写完Q就该采用块注释(参见"块注?/font>")。单行注释之前应该有一个空行。以下是一个Java代码中单行注释的例子Q?/p>
if (condition) { /* Handle the condition. */ ... }
极短的注释可以与它们所要描q的代码位于同一行,但是应该有够的I白来分开代码和注释。若有多个短注释出现于大D代码中Q它们应该具有相同的~进?/p>
以下是一个Java代码中尾端注释的例子Q?/p>
if (a == 2) { return TRUE; /* special case */ } else { return isPrime(a); /* works only for odd a */ }
5.1.4 行末注释(End-Of-Line Comments)
注释界定W?//"Q可以注释掉整行或者一行中的一部分。它一般不用于q箋多行的注释文本;然而,它可以用来注释掉q箋多行的代码段。以下是所有三U风格的例子Q?/p>
if (foo > 1) { // Do a double-flip. ... } else { return false; // Explain why here. } //if (bar > 1) { // // // Do a triple-flip. // ... //} //else { // return false; //}
5.2 文档注释(Documentation Comments)
注意Q此处描q的注释格式之范例,参见"Java源文件范?/font>"
若想了解更多Q参?How to Write Doc Comments for Javadoc"Q其中包含了有关文档注释标记的信?@return, @param, @see)Q?/p>
http://java.sun.com/javadoc/writingdoccomments/index.html
若想了解更多有关文档注释和javadoc的详l资料,参见javadoc的主:(x)
http://java.sun.com/javadoc/index.html
文档注释描述Java的类、接口、构造器Q方法,以及(qing)字段(field)。每个文档注释都?x)被|于注释定界W?**...*/之中Q一个注释对应一个类、接口或成员。该注释应位于声明之前:(x)
/** * The Example class provides ... */ public class Example { ...
注意层(top-level)的类和接口是不羃q的Q而其成员是羃q的。描q类和接口的文档注释的第一?/**)不需~进Q随后的文档注释每行都羃q??使星L(fng)向对?。成员,包括构造函数在内,其文档注释的W一行羃q?|随后每行都羃q?根{?/p>
若你想给出有关类、接口、变量或Ҏ(gu)的信息,而这些信息又不适合写在文档中,则可使用实现块注??.1.1)或紧跟在声明后面的单行注??.1.2)。例如,有关一个类实现的细节,应放入紧跟在cd明后面的实现块注释中Q而不是放在文档注释中?/p>
文档注释不能攑֜一个方法或构造器的定义块中,因ؓ(f)Java?x)将位于文档注释之后的第一个声明与其相兌?/p>
推荐一行一个声明,因ؓ(f)q样以利于写注释。亦卻I
int level; // indentation level int size; // size of table
要优于,
int level, size;
不要不同类型变量的声明攑֜同一行,例如Q?/p>
int foo, fooarray[]; //WRONG!
注意Q上面的例子中,在类型和标识W之间放了一个空|另一U被允许的替代方式是使用制表W:(x)
int level; // indentation level int size; // size of table Object currentEntry; // currently selected table entry
量在声明局部变量的同时初始化。唯一不这么做的理由是变量的初始g赖于某些先前发生的计?/p>
只在代码块的开始处声明变量。(一个块是指M被包含在大括?{"?}"中间的代码。)(j)不要在首ơ用到该变量时才声明之。这?x)把注意力不集中的程序员搞糊涂,同时会(x)妨代码在该作用域内的可移植性?/p>
void myMethod() { int int1 = 0; // beginning of method block if (condition) { int int2 = 0; // beginning of "if" block ... } }
该规则的一个例外是for循环的烦(ch)引变?/p>
for (int i = 0; i < maxLoops; i++) { ... }
避免声明的局部变量覆盖上一U声明的变量。例如,不要在内部代码块中声明相同的变量名:(x)
int count; ... myMethod() { if (condition) { int count = 0; // AVOID! ... } ... }
6.4 cd接口的声?Class and Interface Declarations)
当编写类和接口是Q应该遵守以下格式规则:(x)
- 在方法名与其参数列表之前的左括号"("间不要有I格
- 左大括号"{"位于声明语句同行的末?br>- 叛_括号"}"另v一行,与相应的声明语句寚wQ除非是一个空语句Q?}"应紧跟在"{"之后
class Sample extends Object { int ivar1; int ivar2; Sample(int i, int j) { ivar1 = i; ivar2 = j; } int emptyMethod() {} ... }- Ҏ(gu)与方法之间以I分隔
每行臛_包含一条语句,例如Q?/p>
argv++; // Correct argc--; // Correct argv++; argc--; // AVOID!
复合语句是包含在大括号中的语句序列,形如"{ 语句 }"。例如下面各Dc(din)?/p>
- 被括其中的语句应该较之复合语句羃q一个层?br>- 左大括号"{"应位于复合语句v始行的行;叛_括号"}"应另起一行ƈ与复合语句首行对齐?br>- 大括号可以被用于所有语句,包括单个语句Q只要这些语句是诸如if-else或for控制l构的一部分。这样便于添加语句而无需担心׃忘了加括可(g)引入bug?
一个带q回值的return语句不用小括号"()"Q除非它们以某种方式使返回值更为显见。例如:(x)
return; return myDisk.size(); return (size ? size : defaultSize);
7.4 ifQif-elseQif else-if else语句(if, if-else, if else-if else Statements)
if-else语句应该h如下格式Q?/p>
if (condition) { statements; } if (condition) { statements; } else { statements; } if (condition) { statements; } else if (condition) { statements; } else{ statements; }
注意Qif语句L?{"?}"括v来,避免使用如下Ҏ(gu)引v错误的格式:(x)
if (condition) //AVOID! THIS OMITS THE BRACES {}! statement;
一个for语句应该h如下格式Q?/p>
for (initialization; condition; update) { statements; }
一个空的for语句(所有工作都在初始化Q条件判断,更新子句中完成)(j)应该h如下格式Q?/p>
for (initialization; condition; update);
当在for语句的初始化或更新子句中使用逗号Ӟ避免因用三个以上变量,而导致复杂度提高。若需要,可以在for循环之前(为初始化子句)或for循环末尾(为更新子?使用单独的语句?/p>
一个while语句应该h如下格式
while (condition) { statements; }
一个空的while语句应该h如下格式Q?/p>
while (condition);
7.7 do-while语句(do-while Statements)
一个do-while语句应该h如下格式Q?/p>
do { statements; } while (condition);
7.8 switch语句(switch Statements)
一个switch语句应该h如下格式Q?/p>
switch (condition) { case ABC: statements; /* falls through */ case DEF: statements; break; case XYZ: statements; break; default: statements; break; }
每当一个case着往下执行时(因ؓ(f)没有break语句)Q通常应在break语句的位|添加注释。上面的CZ代码中就包含注释/* falls through */?/p>
7.9 try-catch语句(try-catch Statements)
一个try-catch语句应该h如下格式Q?/p>
try { statements; } catch (ExceptionClass e) { statements; }
一个try-catch语句后面也可能跟着一个finally语句Q不论try代码块是否顺利执行完Q它都会(x)被执行?/p>
try { statements; } catch (ExceptionClass e) { statements; } finally { statements; }
I逻辑相关的代码段分隔开Q以提高可读性?/p>
下列情况应该L使用两个IQ?/p>
- 一个源文g的两个片D?section)之间
- cd明和接口声明之间
下列情况应该L使用一个空行:(x)
- 两个Ҏ(gu)之间
- Ҏ(gu)内的局部变量和Ҏ(gu)的第一条语句之?br>- 块注释(参见"5.1.1"Q或单行注释Q参?5.1.2"Q之?br>- 一个方法内的两个逻辑D之_(d)用以提高可读?
下列情况应该使用I格Q?/p>
- 一个紧跟着括号的关键字应该被空格分开Q例如:(x)
while (true) { ... }注意Q空g应该|于Ҏ(gu)名与其左括号之间。这有助于区分关键字和Ҏ(gu)调用?br>- I白应该位于参数列表中逗号的后?br>- 所有的二元q算W,除了"."Q应该用空格将之与操作数分开。一元操作符和操作数之间不因该加I格Q比如:(x)负号("-")、自?"++")和自?"--")。例如:(x)
a += c + d; a = (a + b) / (c * d); while (d++ = s++) { n++; } printSize("size is " + foo + "\n");- for语句中的表达式应该被I格分开Q例如:(x)
for (expr1; expr2; expr3)- 强制转型后应该跟一个空|例如Q?
myMethod((byte) aNum, (Object) x); myMethod((int) (cp + 5), ((int) (i + 3)) + 1);
命名规范使程序更易读Q从而更易于理解。它们也可以提供一些有x识符功能的信息,以助于理解代码,例如Q不论它是一个常量,包,q是cR?/p>
标识W类?/td> | 命名规则 | 例子 |
?Packages) | 一个唯一包名的前~L全部写的ASCII字母q且是一个顶U域名,通常是comQeduQgovQmilQnetQorgQ或1981qISO 3166标准所指定的标识国家的英文双字W代码。包名的后箋部分Ҏ(gu)不同机构各自内部的命名规范而不相同。这cd名规范可能以特定目录名的l成来区分部?department)Q项?project)Q机?machine)Q或注册?login names)?/td> | com.sun.eng com.apple.quicktime.v2 edu.cmu.cs.bovik.cheese |
c?Classes) | 命名规则Q类名是个一名词Q采用大写混合的方式,每个单词的首字母大写。尽量你的cdz而富于描q。用完整单词,避免~写?除非该羃写词被更q泛使用Q像URLQHTML) | class Raster; class ImageSprite; |
接口(Interfaces) | 命名规则Q大写规则与类名相?/td> | interface RasterDelegate; interface Storing; |
Ҏ(gu)(Methods) | Ҏ(gu)名是一个动词,采用大小写合的方式Q第一个单词的首字母小写,其后单词的首字母大写?/td> | run(); runFast(); getBackground(); |
变量(Variables) | 除了变量名外Q所有实例,包括c,cd量,均采用大写混合的方式,W一个单词的首字母小写,其后单词的首字母大写。变量名不应以下划线或美元符号开_(d)管q在语法上是允许的?br>变量名应短且富于描述。变量名的选用应该易于记忆Q即Q能够指出其用途。尽量避免单个字W的变量名,除非是一ơ性的临时变量。(f)时变量通常被取名ؓ(f)iQjQkQm和nQ它们一般用于整型;cQdQeQ它们一般用于字W型?/td> | char c; int i; float myWidth; |
实例变量(Instance Variables) | 大小写规则和变量名相|除了前面需要一个下划线 | int _employeeId; String _name; Customer _customer; |
帔R(Constants) | cd量和ANSI帔R的声明,应该全部大写Q单词间用下划线隔开?量避免ANSI帔RQ容易引起错? | static final int MIN_WIDTH = 4; static final int MAX_WIDTH = 999; static final int GET_THE_CPU = 1; |
10 ~程惯例(Programming Practices)
10.1 提供对实例以?qing)类变量的访问控?Providing Access to Instance and Class Variables)
若没有够理由,不要把实例或cd量声明ؓ(f)公有。通常Q实例变量无需昑ּ的设|?set)和获?gotten)Q通常q作为方法调用的边缘效应 (side effect)而生?/p>
一个具有公有实例变量的恰当例子Q是cM作ؓ(f)数据l构Q没有行为。亦卻I若你要用一个结?struct)而非一个类(如果java支持l构的话)Q那么把cȝ实例变量声明为公有是合适的?/p>
10.2 引用cd量和cL?Referring to Class Variables and Methods)
避免用一个对象访问一个类的静态变量和Ҏ(gu)。应该用cd替代。例如:(x)
classMethod(); //OK AClass.classMethod(); //OK anObject.classMethod(); //AVOID!
位于for循环中作数器值的数字帔RQ除?1,0?之外Q不应被直接写入代码?/p>
10.4 变量赋?Variable Assignments)
避免在一个语句中l多个变量赋相同的倹{它很难L。例如:(x)
fooBar.fChar = barFoo.lchar = 'c'; // AVOID!
不要赋D符用在Ҏ(gu)与相{关p运符h的地斏V例如:(x)
if (c++ = d++) { // AVOID! (Java disallows) ... }
应该写成
if ((c++ = d++) != 0) { ... }
不要使用内嵌(embedded)赋D符试图提高q行时的效率Q这是编译器的工作。例如:(x)
d = (a = b + c) + r; // AVOID!
应该写成
a = b + c; d = a + r;
10.5 其它惯例(Miscellaneous Practices)
一般而言Q在含有多种q算W的表达式中使用圆括h避免q算W优先问题Q是个好Ҏ(gu)。即使运符的优先对你而言可能很清楚,但对其他人未必如此。你不能假设别的E序员和你一h楚运符的优先?/p>
if (a == b && c == d) // AVOID! if ((a == b) && (c == d)) // RIGHT
设法让你的程序结构符合目的。例如:(x)
if (booleanExpression) { return true; } else { return false; }
应该代之以如下方法:(x)
return booleanExpression;
cM圎ͼ(x)
if (condition) { return x; } return y;
应该写做Q?/p>
return (condition ? x : y);
10.5.3 条gq算W??"前的表达?Expressions before '?' in the Conditional Operator)
如果一个包含二元运符的表辑ּ出现在三元运符" ? : "??"之前Q那么应该给表达式添上一对圆括号。例如:(x)
(x >= 0) ? x : -x;
10.5.4 Ҏ(gu)注释(Special Comments)
在注释中使用XXX来标识某些未实现(bogus)的但可以工作(works)的内宏V用FIXME来标识某些假的和错误的内宏V?/p>
11.1 Java源文件范?Java Source File Example)
下面的例子,展示了如何合理布局一个包含单一公共cȝJava源程序。接口的布局与其怼。更多信息参?cd接口声明"以及(qing)"文挡注释"?/p>
/* * @(#)Blah.java 1.82 99/03/18 * * Copyright (c) 1994-1999 Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. * All rights reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. */ package java.blah; import java.blah.blahdy.BlahBlah; /** * Class description goes here. * * @version 1.82 18 Mar 1999 * @author Firstname Lastname */ public class Blah extends SomeClass { /* A class implementation comment can go here. */ /** classVar1 documentation comment */ public static int classVar1; /** * classVar2 documentation comment that happens to be * more than one line long */ private static Object classVar2; /** instanceVar1 documentation comment */ public Object instanceVar1; /** instanceVar2 documentation comment */ protected int instanceVar2; /** instanceVar3 documentation comment */ private Object[] instanceVar3; /** * ...constructor Blah documentation comment... */ public Blah() { // ...implementation goes here... } /** * ...method doSomething documentation comment... */ public void doSomething() { // ...implementation goes here... } /** * ...method doSomethingElse documentation comment... * @param someParam description */ public void doSomethingElse(Object someParam) { // ...implementation goes here... } }
}
});
//thread.start();
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage(), "ERROR",
JOptionPane.ERROR_MESSAGE);
}
}
if (checkHarf(comp.getText())) {
comp.requestFocus();
JOptionPane.showMessageDialog(null, "full size");
comp.requestFocus();
return false;
}
if (comp.getText().length() > digit) {
JOptionPane.showMessageDialog(null, "exceed digit");
comp.requestFocus();
return false;
}
return true;
}
/**
* 是否为半?br> * @param 字符?br> * @return 半角true 全角false
*/
private boolean checkHarf(String item) {
byte[] bytes = item.getBytes();
int beams = item.length();
if (beams == bytes.length) {
return true;
} else {
return false;
}
}
虽然使用正则表达式能很好的进行字W串的解析、提取、替换,但是对于一些简单的应用Q?/span>
String
cL供的一些方法就可以很好的完成,最H出的就?/span>
split
Ҏ(gu)?/span>
split
Ҏ(gu)能够很方便的字W串按照一定的规则拆分开?/span>
比如对于下面的字W串Q?/span>
Tom,Jane,Tony,Elva,Gigi
只要调用如下的代码就可以各个名字提取出来:(x)
String value = "Tom,Jane,Tony,Elva,Gigi";
String[] names = value.split(",");
for(int i=0,n=names.length;i<n;i++)
{
System.out.println(names[i]);
}
q行l果Q?/span>
Tom
Jane
Tony
Elva
Gigi
看到q个q行l果Q很多h都认?/span> split Ҏ(gu)是按照l定的字W串对字W串q行拆分Q知道碰C下面的问题?/span>
有一个字W串Q中?/span> . 北京 . h(wn) . 学院路。请解析此字W串Qƈ打印输出“中?/span> 北京 h(wn) 学院?/span> ”?/span>
于是写代码如下:(x)
String value = " 中国 . 北京 . h(wn) . 学院?/span> ";
String[] names = value.split(".");
for(int i=0,n=names.length;i<n;i++)
{
System.out.print(names[i]+" ");
}
q行l果Q?/span>
对,没看错!没有M输出Q?/span>
让我们来看看
split
Ҏ(gu)的方法签名吧Q?/span>
public String[] split(String regex)
q里的参数的名称?/span>
regex
Q也是
Regular Expression
Q正则表辑ּQ。这个参数ƈ不是一个简单的分割用的字符Q而是一个正则表辑ּQ看?/span>
split
Ҏ(gu)的实C码就更坚定了我们的信心:(x)
public String[] split(String regex, int limit) {
return Pattern.compile(regex).split(this, limit);
}
split
的实现直接调用的
Matcher
cȝ
split
的方法。读者已l知道,?/span>
.
”在正则表达式中有特D的含义Q因此我们用的时候必进行{义?/span>
修改代码如下Q?/span>
private static void split2()
{
String value = " 中国 . 北京 . h(wn) . 学院?/span> ";
String[] names = value.split("\\.");
for(int i=0,n=names.length;i<n;i++)
{
System.out.print(names[i]+" ");
}
}
q行l果
Q?span lang="EN-US">
中国
北京
h(wn)
学院?/span>
1. 配置文g
Log4J配置文g的基本格式如下:(x)
#配置根Logger
log4j.rootLogger = [ level ] , appenderName1 , appenderName2 , ?/p>
#配置日志信息输出目的地Appender
log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
?
log4j.appender.appenderName.optionN = valueN
#配置日志信息的格式(布局Q?br />log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
?
log4j.appender.appenderName.layout.optionN = valueN
其中 [level] 是日志输出别,共有5U:(x)
FATAL 0
ERROR 3
WARN 4
INFO 6
DEBUG 7
Appender 为日志输出目的地QLog4j提供的appender有以下几U:(x)
org.apache.log4j.ConsoleAppenderQ控制台Q,
org.apache.log4j.FileAppenderQ文Ӟ(j)Q?br />org.apache.log4j.DailyRollingFileAppenderQ每天生一个日志文Ӟ(j)Q?br />org.apache.log4j.RollingFileAppenderQ文件大到达指定尺寸的时候生一个新的文Ӟ(j)Q?br />org.apache.log4j.WriterAppenderQ将日志信息以流格式发送到L指定的地方)(j)
LayoutQ日志输出格式,Log4j提供的layout有以下几U:(x)
org.apache.log4j.HTMLLayoutQ以HTML表格形式布局Q,
org.apache.log4j.PatternLayoutQ可以灵zd指定布局模式Q,
org.apache.log4j.SimpleLayoutQ包含日志信息的U别和信息字W串Q,
org.apache.log4j.TTCCLayoutQ包含日志生的旉、线E、类别等{信息)(j)
打印参数: Log4J采用cMC语言中的printf函数的打印格式格式化日志信息Q如?
%m 输出代码中指定的消息
%p 输出优先U,即DEBUGQINFOQW(xu)ARNQERRORQFATAL
%r 输出自应用启动到输出该log信息耗费的毫U数
%c 输出所属的cȝQ通常是所在类的全?
%t 输出产生该日志事件的U程?
%n 输出一个回车换行符QW(xu)indowsq_为“\\r\\n”,Unixq_为“\\n?
%d 输出日志旉点的日期或时_(d)默认格式为ISO8601Q也可以在其后指定格式,比如Q?d{yyy MMM dd HH:mm:ss , SSS}Q输出类|(x)2002q?0?8日?22 Q?10 Q?28 Q?921
%l 输出日志事g的发生位|,包括cȝ名、发生的U程Q以?qing)在代码中的行数。D例:(x)Testlog4.main(TestLog4.java: 10 )
2. 在代码中初始化Logger:
1Q在E序中调用BasicConfigurator.configure()Ҏ(gu)Q给根记录器增加一个ConsoleAppenderQ输出格式通过PatternLayout设ؓ(f)%-4r [%t] %-5p %c %x - %m%nQ还有根记录器的默认U别是Level.DEBUG.
2Q配|放在文仉Q通过命o(h)行参C递文件名字,通过PropertyConfigurator.configure(args[x])解析q|;
3Q配|放在文仉Q通过环境变量传递文件名{信息,利用log4j默认的初始化q程解析q|;
4Q配|放在文仉Q通过应用服务器配|传递文件名{信息,利用一个特D的servlet来完成配|?/p>
3. Z同的 Appender 讄日志输出U别Q?br />当调试系l时Q我们往往注意的只是异常别的日志输出Q但是通常所有别的输出都是攑֜一个文仉的,如果日志输出的别是BUGQ?那就慢慢L吧?br />q时我们也许?x)想要是能把异常信息单独输出C个文仉该多好啊。当然可以,Log4j已经提供了这L(fng)功能Q我们只需要在配置中修改Appender的Threshold p实现,比如下面的例子:(x)
[配置文g]
### set log levels ###
log4j.rootLogger = debug , stdout , D , E
### 输出到控制台 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
### 输出到日志文?###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG ## 输出DEBUGU别以上的日?br />log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 保存异常信息到单独文?###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/error.log ## 异常日志文g?br />log4j.appender.D.Append = true
log4j.appender.D.Threshold = ERROR ## 只输出ERRORU别以上的日?!!
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
Java Web StartQ以下简UJWSQ是SUN提供的一U通过Web来部|和发布Java E序的新技术,它既可以用来发布ApplicationQ也可以用来发布AppletQ它获去q全球Java技术最?jng)_意奖。它仅在W一ơ运行时下蝲E序Q以后的事情Q就全全交给JWS,包括版本的自动更新和l护。这是我们曾l梦寐以求的事情Q程序运行在客户端(本地q行Q当然有_的速度Q,但不用去安装配置客户端,也不用去考虑版本升后对客户端的l护Q这是JWS提供l我们的好处之一。OKQ下面我们就来看看如何玩转JWSQ本文仅用发布Application来做说明?br />pȝ环境QWin2000Professional+Tomcat3.2.1+JDK1.3?br />一QJWS?br />JWS主要用来通过|络部v你的应用E序Q它h安全、稳定、易l护、易使用的特炏V用戯问用JWS部v应用E序的站点,下蝲发布的应用程序,既可以在U运行,也可以通过JWS的客L(fng)ȝq行已下载的应用E序。对同一个应用程序,在第一ơ运行时下蝲Q以后每ơ运行时QJWS的客L(fng)?x)自动去探测是否有版本更斎ͼ有更新就自动下蝲新版本,没有更新q接运行本地当前版本,所有的ȝ(ch)全由JWSL担。好Q下面我们就一步一步来搭徏JWS
二:(x)搭徏支持JWS的Web站点
W一步:(x)你的Tomcat3.2.1已经正常q{
W二步:(x)扑ֈTomcatHOME/conf下的web.xml文gQ在其中d<mime-type>
application/x-java-jnlp-file
</mime-type>
以支持JNLP文g?br />三:(x)部v应用E序
W一步:(x)开发你希望发布的应用程?br />W二步:(x)把应用程序及(qing)所用到的所有资源打成一个或多个jar?br />W三步:(x)如果你的应用E序不会(x)用到Mq行q个应用E序的机器的本地资源Q那么,你的应用E序可以部|了?br />W四步:(x)如果你的应用E序用到了运行这个应用程序的机器的本地资源,那么Q你的应用程序就必须先签名然后才可以发布?br />W五步:(x)如何l应用程序签?br />1Q首先确保你已经完全安装了Java2的环境,有keytool工具Q它位于J2SE SDk的bin目录下。这一般不?x)有问题?br />2Q到Dos状态下Q进入你需发布应用E序的jar包所在的目录Q运行下面这句话
keytool -genkey -keystore myKeystore -alias jwstest
它将?x)提CZ输入用户名、密码等Q不用理它,按照提示随便输入卛_Q但一定要C密码。运行结束它?yu)?x)在当前\径下创徏名ؓ(f)myKeystore的文件?br />3Q如果你惛_看一下刚才生成的myKeystore文g的内容,可以使用下面q句话:(x)
keytool -list -keystore myKeystore
昄出来应该cM如下Q?br />Keystore type: jks
Keystore provider: SUN
Your keystore contains 1 entry:
jwstest, Tue Nov 23 19:29:32 PST 2001, keyEntry,
Certificate fingerprint (Test):
C3:A9:CD:F3:D3:AC:4D:3F:3C:5B:AF:9E:CF:0D:46:5C
4Q对你需发布应用E序的jar包进行签名,q行下面q句话:(x)
jarsigner -keystore myKeystore yourtest.jar jwstest
其中yourtest.jar是你的jar包名Q你需要修改它Q别的就不必修改了。运行时?x)提CZ输入密码Q就是你刚才在生成myKeystore文g时设定的密码?br />W六步:(x)部v应用E序的jar包?br />1Q在Tomcat的webapps中新建目录JWSTest
2Q在JWSTest下新建目录apps,META-INFQW(xu)EB-INF
3Q在apps下新建目录images和lib
4Q在META-INF中拷入MANIFEST.MF
5Q在WEB-INF中拷入web.xml
6Q把已经准备好的jar包拷入lib目录?br />四:(x)Jsp面
W一步:(x)~写用于Web讉K的页面index.jsp如下Q?br /><%@page contentType="text/html;charset=gb2312"%>
<html>
<title>JWS Test</title>
<head>
<SCRIPT LANGUAGE="Javascript">
function insertLink(url, name) {
document.write("<a href=" + url + ">" + name + "</a><br><br>");
}
insertLink("http://你的IP:8080/ JWSTest /apps/JWSTest.jnlp"," JWSTest ");
</SCRIPT>
</head>
<body>
</body>
</html>
W二步:(x)在jsp中添加检访问的客户端是否已l安装了JWS的客L(fng)的代码,CZ如下Q?br /><%@page contentType="text/html;charset=gb2312"%>
<html>
<title> JWS Test </title>
<head>
<SCRIPT LANGUAGE="Javascript">
var javawsInstalled = 0;
isIE = "false";
if (navigator.mimeTypes && navigator.mimeTypes.length) {
x = navigator.mimeTypes['application/x-java-jnlp-file'];
if (x) javawsInstalled = 1;
} else {
isIE = "true";
}
function insertLink(url, name) {
if (javawsInstalled) {
document.write("<a href=" + url + ">" + name + "</a><br><br>");
} else {
document.write("<a href=" + url + ">"+ name +"</a><br><br>");
}
}
</SCRIPT>
<SCRIPT LANGUAGE="VBScript">
on error resume next
If isIE = "true" Then
If Not(IsObject(CreateObject("JavaWebStart.IsInstalled"))) Then
javawsInstalled = 0
Else
javawsInstalled = 1
End If
End If
</SCRIPT>
<SCRIPT LANGUAGE="Javascript">
if(javawsInstalled){
insertLink("http://你的IP:8080/ JWSTest /apps/JWSTest.jnlp"," JWSTest ");
}else{
//通知用户要先安装JWS的客L(fng)Q你可以自己提供下蝲或是直接链接到Sun的JWS下蝲?br />//分ؓ(f)两种Q如果客L(fng)已经安装了Javaq行环境Q则只要下蝲javaws-1_0_1_01-win-int.exe卛_?br />//如果客户端没有安装Javaq行环境Q则要下载完整的javaws-1_0_1_01-win-int-rt.exe?br />}
</SCRIPT>
</head>
<body>
</body>
</html>
五:(x)JNLP文g
W一步:(x)下面我们来编写JWS的核心配|文件JNLPQ有了它Q才能将以上各部分联pv来,真正让JWSq{h。JNLP文gW合标准的XML语法Q实质就是一个XML文g。当?dng)~写它的最好方式是对已写好的JNLPq行改写。JWSTest.jnlpCZ如下Q?br /><?xml version="1.0" encoding="utf-8"?>
<!-- JNLP File for SwingSet2 Demo Application -->
<jnlp
spec="1.0+"
codebase="http://你的IP:8080/JWSTest/apps"
href=" JWSTest.jnlp">
<information>
<title> JWS Test </title>
<vendor>YOUR Name</vendor>
<homepage href=" JWSTest.html"/>
<description> JWS Test </description>
<icon href="images/ JWSTest.jpg"/>
<offline-allowed/>
</information>
<security>
<all-permissions/>
</security>
<resources>
<j2se version="1.3"/>
<jar href="lib/ JWSTest.jar"/>
</resources>
<application-desc main-class="q行启动的主c?/>
</jnlp>
W二步:(x)部分JNLP的关键语?br /><jnlp>元素
specQ必L1.0?qing)以上版本,q里?.0+Q不需修改?br />codebaseQ资源的URLQ是JNLP指向各连接的起始处,需自行修改?br />HrefQJNLP文g相对codebase的存放位|,和JNLP文g的全名,需自行修改?br /><infomation>元素
TitleQ发布的应用E序单标题,需自行修改?br />VendorQ发行商信息Q可以写上你的大名,需自行修改?br />HomepageQ存放有兛_用程序的相关文档的URLQ如help文g{,可有可无?br />DescriptionQ对应用E序的描qͼ可以有多?lt;description></description>Q可有可无?br />IconQ用户下载你的应用程序后Q在JWS里显C的图标的URLQ应是gif或jpeg格式。需自行修改?br />Offline-allowedQ选择,允许用户ȝq行应用E序Q一般都?x)有Q不用修攏V?br /><security>元素
选择,如果没有指明<security>Q默认是不允许应用程序访问用L(fng)本地资源Q即应用E序是沙p行?br />如果讑֮?lt;all-permissions/>Q则表示允许应用E序讉K用户的本地资源。一般都?x)设定此倹{?br /><resource>元素
<j2se version = 指定jdk版本>
<jar href = 指定需发布的应用程序的jar包存攄位置>
<application-desc>元素
main-classQ应用程序运行启动的ȝ
<argument>Q应用程序运行时的参敎ͼ可以有多个,每一个参数用一?lt;argument>参数</argument>?br />xQ你已经完全构徏了运转JWS的各部g?br />六:(x)完整发布和测?br />前面我们已经准备好了需发布的应用程序的jar包,也写好了用来讉K的jsp文g和服务器端的核心jnlp文g?br />W一步:(x)在JWSTest下新建目录jsp。把index.jsp拷入jsp目录?br />W二步:(x)把jnlp文g直接拷入apps目录下?br />W三步:(x)在浏览器里输?http://localhost:8080/JWSTest/jsp/index.jsp 卛_讉K到jsp面。页面应出现JWSTest字样?br />W四步:(x)点击JWSTestQ连接到apps下的JWSTest.jnlp文gQJWS启动Q开始下载你发布的应用程序?br />W五步:(x)下蝲完毕Q直接运行即可。以后,你也可以直接q行JWS客户端里已下载的应用E序?br />不出意外Q应恭喜你已l开始n受JWS带来的乐了?br />七:(x)常见问题
通过上面的讲qͼ你一定能体会(x)到JWS的易用性。或怺情ƈ没有那么单,以我的用经验,q会(x)有许多问题出玎ͼ在这里挑几个l常出现的问题,l出相应解决Ҏ(gu)Q让大家走弯\Q而n受更多的乐趣?br />问题一QJWS不能q行QJNLP文g像普通XML文g一hC在Browser?br />解决办法Q请修改tomcat里,发布E序的\径中的web.xml?br />在其中添?lt;mime-type>
application/x-java-jnlp-file
</mime-type>
以支持JNLP文g?br />问题二:(x)不能下蝲资源或下载资源失?br />解决办法Q请卸蝲JWS的客L(fng)Qƈ注册表里有关JWS的项目都删除Qƈ保program Files下的Java Web Start目录已被删除Q然后,重装JWS?br />问题三:(x)下蝲资源中有未签名文?br />解决办法Q?Q确保所有的jar包及(qing)其他资源都进行过{?br />2Q确保整个资源中Q没有中文的命名。好像签名工具不支持中文命名的文件名Q所以未{ֈ名。这可让我郁闷了一下午哦?br />3Q察看已l签名的jar包中Qmeta-inf路径下的jwstest.sfQjwstest是你在进行签名时-alias后的命名Q文Ӟ他详l的列出了所有已{的文Ӟ以分析签名失败的原因?/span>
http://www.itpub.net/595150.html
<?xml version="1.0" encoding="utf-8"?>
<!-- JNLP File for SwingSet2 Demo Application -->
<jnlp
spec="1.0+"
codebase="href=" JWSTest.jnlp">
<information>
<title> JWS Test </title>
<vendor>YOUR Name</vendor>
<description> JWS Test </description>
<offline-allowed/>
</information>
<security>
<all-permissions/>
</security>
<resources>
<j2se version="1.4"/>
<jar href="lib/xx.jar"/>
</resources>
<application-desc main-class="fullScreen.FullScreenTest"/>
</jnlp>