﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-子在川上曰-随笔分类-Java</title><link>http://www.blogjava.net/chengang/category/8014.html</link><description>　　　　逝者如斯乎不舍昼夜</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 06:42:21 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 06:42:21 GMT</pubDate><ttl>60</ttl><item><title>程序DEBUG：查找类所在的JAR包</title><link>http://www.blogjava.net/chengang/archive/2006/09/13/69311.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Wed, 13 Sep 2006 02:00:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/09/13/69311.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/69311.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/09/13/69311.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/69311.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/69311.html</trackback:ping><description><![CDATA[
		<p>在调试程序解决程序BUG时，我们常要看看所调用的类来自于那一个JAR包。要实现这一目的可以监看如下方法：</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #000000">org.jbpm.JbpmConfiguration.</span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000">.getProtectionDomain()<br /></span>
		</div>
		<p>
				<br />从下面的信息可以清楚看到JbpmConfiguration类来自于<span style="COLOR: #000000">D:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">jbpm</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">starters</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">kit</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">3.1</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">jbpm</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">build</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">jbpm</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">3.1</span><span style="COLOR: #000000">.jar</span>：</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #000000">ProtectionDomain  (file:</span>
				<span style="COLOR: #000000">/</span>
				<span style="COLOR: #000000">D:</span>
				<span style="COLOR: #000000">/</span>
				<span style="COLOR: #000000">jbpm</span>
				<span style="COLOR: #000000">-</span>
				<span style="COLOR: #000000">starters</span>
				<span style="COLOR: #000000">-</span>
				<span style="COLOR: #000000">kit</span>
				<span style="COLOR: #000000">-</span>
				<span style="COLOR: #000000">3.1</span>
				<span style="COLOR: #000000">/</span>
				<span style="COLOR: #000000">jbpm</span>
				<span style="COLOR: #000000">/</span>
				<span style="COLOR: #000000">build</span>
				<span style="COLOR: #000000">/</span>
				<span style="COLOR: #000000">jbpm</span>
				<span style="COLOR: #000000">-</span>
				<span style="COLOR: #000000">3.1</span>
				<span style="COLOR: #000000">.jar </span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">no signer certificates</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000">)<br /> sun.misc.Launcher$AppClassLoader@7259da<br /> </span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">no principals</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000">
						<br /> java.security.Permissions@17ba38f (<br /> (java.io.FilePermission \D:\jbpm</span>
				<span style="COLOR: #000000">-</span>
				<span style="COLOR: #000000">starters</span>
				<span style="COLOR: #000000">-</span>
				<span style="COLOR: #000000">kit</span>
				<span style="COLOR: #000000">-</span>
				<span style="COLOR: #000000">3.1</span>
				<span style="COLOR: #000000">\jbpm\build\jbpm</span>
				<span style="COLOR: #000000">-</span>
				<span style="COLOR: #000000">3.1</span>
				<span style="COLOR: #000000">.jar read)<br /> (java.lang.RuntimePermission exitVM)<br />)</span>
		</div>
		<br />查看这样的信息是很有用的。比如运行的系统中有可能存在有两个JAR包同时含有某一个类，因为JAVA的ClassLoader有先后顺序。你可能发现自己无法怎么改程序，但运行起来却象根本没有改过一样，那么原因可能就出在这里。<br /><br />另外，还可以用getMethod得到所有的方法，这可以确认你增加的方法是否已经装载到JVM中了<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">org.jbpm.JbpmConfiguration.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">.getMethods()</span></div><img src ="http://www.blogjava.net/chengang/aggbug/69311.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-09-13 10:00 <a href="http://www.blogjava.net/chengang/archive/2006/09/13/69311.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个体现Java接口及工厂模式优点的例子</title><link>http://www.blogjava.net/chengang/archive/2006/09/10/68824.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Sun, 10 Sep 2006 09:47:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/09/10/68824.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/68824.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/09/10/68824.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/68824.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/68824.html</trackback:ping><description><![CDATA[原2004年初发于CSDN，后图片丢失，现补上。陈刚 from <a href="http://www.chengang.com.cn">www.chengang.com.cn</a><br /><br /><br />     随着模式概念的普及，了解模式和使用模式的程序员越来越多，很多人在学习模式的时候，都会有这样一种疑惑：“有必要搞得这么复杂吗？”。的确，因为教程的例子过于简单化（这样方便读者学习），或者是作者选例子的时候并没有很好体现所讲模式的优点，很多情况下如果仅就其例子的问题来说，用模式是太复杂了。因此才导致这样的误解：“模式就是把简单的问题复杂化吗？”。当然不是，随着你开发实践的不断丰富，你终会发现模式强大威力，而且模式也并非贵族化的编程方式，它就是一些经过提炼了的解决问题的方法技巧。 
<div> </div><div>      通过学习模式，程序员开始告别过去准直线式的代码方式，模式开扩了我们的视野，强化了我们面向对象编程的思维方式。然而现在又出现了另一个普遍的问题，盲目应用模式。模式是问题的解决方案，先有问题才有模式，模式是依附于所要解决的问题的而生的。必须了解模式在很多情况下是以提高代码的复杂度为代价来增强灵活性、可复用性。如果在自已的代码中使用某一模式仅只提高了代码的复杂度，而其它方面收效甚微，或者某部份代码根本就不存在灵活性及高复用性的需求，那么我们就没有必要为使用模式而放弃更直观简单的代码写法。</div><div> </div><div>      一流的高手90%精力关注问题的解决方案，因为找到了好的解决方案，再写起代码会很轻松代码也简洁流畅，看这样的代码是一种享受和提高；二流的熟手90%精力关注代码实现，因为问题的解决方案并非最佳，实现的代码也会比较复杂；三流菜鸟记流水帐,90%精力在敲键盘，常常做了大半才发现行不通，回过头来再用90%的时间敲键盘，根本不会用到任何模式，写出来的代码的只有他自已才能看懂。做出来的软件也是支离破碎，做一丁点改动都要大费周折，而且你还不知道改动后会产生什么问题，大有住危房里的感觉。</div><div> </div><div>      在这里还是举一个滥用模式的例子吧。我曾参与过一个大集团公司ＯＡ系统的第二期开发，开发沿用原有代码架构并增加新的功能模块。文档很少我读原代码时就被它程序里的代码转来转去搞得头大如斗，最后读懂了：原代码架构总体采用工厂模式，而且是最复杂的抽象工厂模式。它把所有模块类都通过工厂生成还工厂套工厂，并且每一个模块类都有一个接口，每个接口也只有一个模块现实类，因为涉及权限控制还用了代理(proxy)模式。　读懂代码后我开始嵌入代码，发现每新增一个类，都要到六个Java文件中去增加相应代码，而在类中每增加一个方法，也要到它的接口等四个Java文件中去增加相应代码。天呀！！！记得当时我的小姆指常会不听使唤，就是因为频繁的使用Ctrl+C 、Ctrl+V，小姆指按着Ctrl键给累的。整个项目组苦不堪言，真烦透了。项目结束后我回顾发现：代理模式用得还对（现在针对权限这类横向控制有AOP编程这种新的解决办法了）但工厂模式在这里根本就是画蛇添足，不仅没有解决什么问题，反而增加代码复杂度和耦合性，降低了开发效率连维护难度都提高了。而且那种每个类简单的加一个接口的方式，更是没有道理，这让我很想说周星驰说过的一句话：“球~~~不是这么踢~~~~的，接口~~~不是这么用~~~的”。言归正传，我们先来看这样一个常见问题：某系统需要支持多种类型的数据库。用过Oracle、MSSQL等数据库的人都知道，它们的SQL编写方式都各有些不同。比如说Oracle的唯一标识自动+1字段用的是序列，MSSQL改一下字段属性就成了，还有各种各自特有的SQL用法。为了支持多数据库，难道我们要开发多套系统？当然NO。请看下面的解决方案。</div><div> </div><div>      即然数据库存在多种，我们可以将系统中所有对数据库的操作抽象出来，写成一个个方法组合到一个类中，有几种数据库我们就写几个这样的类。具体设计类图如下：</div><div><img height="249" alt="20060910.gif" src="http://www.blogjava.net/images/blogjava_net/chengang/java/20060910.gif" width="500" border="0" /></div><div> </div><div> </div><div>简要说明：</div><ul><li>OracleDataOperate、SqlserverDataOperate、MysqlDataOperate，分别代表Oracle、Sqlserver、Mysql这三种数据库的操作类。继承自AbstractDataOperate 
</li><li>AbstractDataOperate是一个抽象类，包含了那些不同种类数据库都是一样代码的操作方法。继承自DataOperate 
</li><li>DataOperate是上面说的数据操作类的统一接口，只有两个方法：取得一条记录、插入一条记录。 
</li><li>DataOperateFactory是一个工厂方法，统一用它的方法来得到数据库操作类的实例。 
</li><li>SampleClass是我们系统的某个功能模块的类。 
</li><li>People是一个实体类，代表一条记录。三个字段　oid唯一标识符、name姓名、date生日。</li></ul><div> </div><div><strong>详细说明：</strong></div><div>１、所有系统功能模块类只认DataOperat这个接口还不必管具体的实现类是OracleDataOperate还SqlserverDataOperate。DataOperate源代码如下：</div><div><b>public</b><b>interface</b> DataOperate {</div><div align="left">    //根据记录的唯一标识取出一条记录</div><div align="left">    People getPeople(String oid);</div><div align="left">    //插入一条记录</div><div align="left">    <b>boolean</b> insertPeople(People people);</div><div>}</div><div> </div><div>２、AbstractDataOperate、OracleDataOperate、SqlserverDataOperate、MysqlDataOperate都是继承DataOperate接口的，没什么好说的，省略。</div><div> </div><div>３、DataOperateFactory。我们看看工厂方法怎么写的。</div><div align="left"><b>public</b><b>class</b> DataOperateFactory {</div><div align="left">    <b>public</b><b>static</b><b>final</b><b>int</b> ORACLE = 0; //定义三个表示数据库类型的常量</div><div align="left">    <b>public</b><b>static</b><b>final</b><b>int</b> MYSQL = 1;</div><div align="left">    <b>public</b><b>static</b><b>final</b><b>int</b> SQLSERVER = 2;</div><div align="left"> </div><div align="left">    <b>private</b><b>static</b> DataOperate db;</div><div align="left">    <b>private</b><b>static</b><b>int</b> dataType = MYSQL;</div><div align="left">    /**</div><div align="left">     * 根据数据库类型(dataType)取得一个数据库操作类的实例，</div><div align="left">     * 这里对DataOperate使用了单例模式，因为OracelDataOperate等都是无状态的工具类，</div><div align="left">     * 所以整个系统只保留一个实例就行了。</div><div align="left">     * </div><div align="left">     * <b>@return</b> 返回的是接口，客户端不必关心具体是用那个实现类</div><div align="left">     */</div><div align="left">    <b>public</b><b>static</b> DataOperate getInstance() {</div><div align="left">        <b>if</b> (db == <b>null</b>) {</div><div align="left">            <b>if</b> (dataType == ORACLE) //根据dateType返回相应的实现类</div><div align="left">                <b>return</b><b>new</b> OracelDataOperate();</div><div align="left">            <b>if</b> (dataType == MYSQL)</div><div align="left">                <b>return</b><b>new</b> MysqlDataOperate();</div><div align="left">            <b>if</b> (dataType == SQLSERVER)</div><div align="left">                <b>return</b><b>new</b> SqlserverDataOperate();</div><div align="left">        }</div><div align="left">        <b>return</b> db;</div><div align="left">    }</div><div>}</div><div> </div><div>４、接下来就看看使用端是如何调用工厂方法和使用数据操作类的。</div><div align="left">/**</div><div align="left"> * 系统某个功能类</div><div align="left"> */</div><div align="left"><b>public</b><b>class</b> SampleClass {</div><div align="left"><b>private</b> DataOperate db; //声明一个数据库操作类，注意这里用的是接口噢</div><div align="left">    /**某方法*/</div><div align="left">    <b>public</b><b>void</b> sampleMethod() {</div><div align="left">        db = DataOperateFactory.getInstance();//得到单一实例</div><div align="left">        People p = db.getPeople("123"); //取得一条记录</div><div align="left">        db.insertPeople(p);//再插回去</div><div align="left">    }</div><div align="left">}</div><div align="left"> </div><div align="left">　　我们发现SampleClass中根本没有出现OracelDataOperate、MysqlDataOperate等的影子，这就是接口的威力。客户端不必针对OracelDataOperate等写不同的代码，它只关心DataOperate即可，具体要取那个类的逻辑就由DataOperateFactory负责了。</div><div align="left"> </div><div align="left">总结：</div><ul><li><div align="left">从例子中我们可以看到什么是面向接口的编程方式。SampleClass使用数据操作类可以不必关心具体是那个类，只要是符合接口的都行</div></li><li><div align="left">要实例？只须调用DataOperateFactory.getInstance()即可，其它的交于DataOperateFactory这个工厂来做吧，使用端什么都不用关心。</div></li><li><div align="left">我们要支持新的数据库类型，只须要象OracelDataOperate那样，再写一个继承AbstractDataOperate的类即可，比如SysbaseDataOperate。然后到DataOperateFactory中加入相应代码即可。</div></li><li><div align="left">如果我们想要可配置性更高，可以用<b>private</b><b>static</b><b>int</b> dataType = MYSQL;中的值设置到一个文本文件中。</div></li></ul><div align="left">　　对于开发支持多种数据库的系统，强烈建议使用hibernate，我现在做的系统就是用hibernate的，开发时用Mysql，到要给客户时将数据库换了DB2，程序不用做任何改动，真正的无逢移植。不过这样，本文所提到的方法就没什么用了.</div><img src ="http://www.blogjava.net/chengang/aggbug/68824.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-09-10 17:47 <a href="http://www.blogjava.net/chengang/archive/2006/09/10/68824.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA Appliation下取得资源文件的路径</title><link>http://www.blogjava.net/chengang/archive/2006/09/08/68585.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Fri, 08 Sep 2006 10:54:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/09/08/68585.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/68585.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/09/08/68585.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/68585.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/68585.html</trackback:ping><description><![CDATA[今天要写一个单元测试，这个单元测试类要去读和它同目录的一个XML文件。它的位置如下：<br />ConfigFactoryImplTest要去读取boss-connector-service.xml。<br /><br /><img height="466" alt="200609081.jpg" src="http://www.blogjava.net/images/blogjava_net/chengang/java/200609081.jpg" width="449" border="0" /><br /><br />那么如果得到这个文件呢？先看下面的一个对路径的测试代码<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.io.File;<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> PathTest {<br />  </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> main(String[] args) </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Exception {<br />    System.out.println(<br />    Thread.currentThread().getContextClassLoader().getResource(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">));<br />    System.out.println(PathTest.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">.getClassLoader().getResource(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">));<br />    System.out.println(ClassLoader.getSystemResource(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">));<br />    System.out.println(PathTest.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">.getResource(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">));<br />    System.out.println(PathTest.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">.getResource(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">));<br />    System.out.println(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> File(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">).getAbsolutePath());<br />    System.out.println(System.getProperty(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">user.dir</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">));<br />  }<br />}</span></div><br /><br />打印各种路径结果如下：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">file:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">E:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr_projects2</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">applications</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">boss</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">connector</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">target</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">classes</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"><br />file:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">E:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr_projects2</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">applications</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">boss</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">connector</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">target</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">classes</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"><br />file:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">E:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr_projects2</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">applications</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">boss</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">connector</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">target</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">classes</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"><br />file:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">E:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr_projects2</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">applications</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">boss</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">connector</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">target</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">classes</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">com</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">boss</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">config</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"><br />file:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">E:</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr_projects2</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">applications</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">boss</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">connector</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">target</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">classes</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"><br />E:\wxxr_projects2\wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">applications\wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">boss</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">connector<br />E:\wxxr_projects2\wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">applications\wxxr</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">boss</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">connector<br /></span></div><br /><br />发现PathTest.<span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">.getResource(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">)得到了绝对路径，嗯，就它了。于是将ConfigFactoryImplTest类里的代码书写如下（这里是用DOM来读XML）：<br /></span><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Element getRootElement() </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Exception {<br /></span><span style="COLOR: #000000">        DocumentBuilderFactory dbf </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> DocumentBuilderFactory.newInstance();<br />        DocumentBuilder db </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> dbf.newDocumentBuilder();<br />        Document doc </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> db.parse(ConfigFactoryImplTest.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">.getResource(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">) </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">boss-connector-service.xml</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> doc.getDocumentElement();<br />    }<br /></span></div><br /><br />后记：<br />得到资源文件的路径，在不同的环境（如：Eclipse RCP、Tomcat、Weblogic、简单的Java Application），方法都是略有不同的。具体的环境要具体分析。<img src ="http://www.blogjava.net/chengang/aggbug/68585.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-09-08 18:54 <a href="http://www.blogjava.net/chengang/archive/2006/09/08/68585.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>聚集Collection的技巧</title><link>http://www.blogjava.net/chengang/archive/2006/04/01/38611.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Sat, 01 Apr 2006 07:48:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/04/01/38611.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/38611.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/04/01/38611.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/38611.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/38611.html</trackback:ping><description><![CDATA[
		<div>1、  MAP<br />特点：同键的新值将覆盖旧值。<br />示例：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">        Map</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String, String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> map </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> HashMap</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String, String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br />        String str;<br />        str </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> map.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">a</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">str=null</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        str </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> map.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">b</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">str=a</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        str </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> map.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">c</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">str=b 新值覆盖旧值，最后map只有(1,c)一个值。返回的b是被覆盖的值<br /></span></div><br />循环遍历：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">        Map</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String, Long</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> map </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> HashMap</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String, Long</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br />        map.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">a</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Long(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">));<br />        map.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">b</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Long(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">));<br /><br />        </span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000"> (Map.Entry</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String, Long</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> entry : map.entrySet()) {<br />            String key </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> entry.getKey();<br />            Long value </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> entry.getValue();<br />        }<br /></span></div><br />2、Set<br />特点：无序排列，不会存在重复的值，添加重复值也不会报错.Set可以加入null值<br />示例：</div>
		<div>
				<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
						<span style="COLOR: #000000">        Set</span>
						<span style="COLOR: #000000">&lt;</span>
						<span style="COLOR: #000000">String</span>
						<span style="COLOR: #000000">&gt;</span>
						<span style="COLOR: #000000"> set </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">new</span>
						<span style="COLOR: #000000"> HashSet</span>
						<span style="COLOR: #000000">&lt;</span>
						<span style="COLOR: #000000">String</span>
						<span style="COLOR: #000000">&gt;</span>
						<span style="COLOR: #000000">();<br />        </span>
						<span style="COLOR: #0000ff">boolean</span>
						<span style="COLOR: #000000"> b;<br />        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> set.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">1</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=true</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> set.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">2</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=true</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> set.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">1</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=false</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> set.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">2</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=false 返回值为false，表示没有加入<br /></span>
				</div>
				<br />3、List<br />特点：有序排序，可以加入重复的元素<br />示例：</div>
		<div>
				<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
						<span style="COLOR: #000000">        Arrays.asList(</span>
						<span style="COLOR: #0000ff">new</span>
						<span style="COLOR: #000000"> String[] {</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">11</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">, </span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">222</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000"> });</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">返回一个不可改的List</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        List</span>
						<span style="COLOR: #000000">&lt;</span>
						<span style="COLOR: #000000">String</span>
						<span style="COLOR: #000000">&gt;</span>
						<span style="COLOR: #000000"> l </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> Arrays.asList(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">11</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">, </span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">222</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">, </span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">333</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);<br />        l.subList(</span>
						<span style="COLOR: #000000">1</span>
						<span style="COLOR: #000000">, </span>
						<span style="COLOR: #000000">2</span>
						<span style="COLOR: #000000">); </span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">由第二个和第三个元素生成一个新List</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">
								<br />        ArrayList</span>
						<span style="COLOR: #000000">&lt;</span>
						<span style="COLOR: #000000">String</span>
						<span style="COLOR: #000000">&gt;</span>
						<span style="COLOR: #000000"> list </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">new</span>
						<span style="COLOR: #000000"> ArrayList</span>
						<span style="COLOR: #000000">&lt;</span>
						<span style="COLOR: #000000">String</span>
						<span style="COLOR: #000000">&gt;</span>
						<span style="COLOR: #000000">(l); </span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">生成一个可改的List</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        </span>
						<span style="COLOR: #0000ff">boolean</span>
						<span style="COLOR: #000000"> b;<br />        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> list.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">11</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=true  List可以加入重复的元素</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> list.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">11</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=true<br /></span>
				</div>
				<br />4、Collections<br />特点：Collections.class是集合的工具方法类<br />示例：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">        List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> list1 </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> ArrayList</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br />        List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> list </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> ArrayList</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br /><br />        Collections.sort(list); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">排序</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> pos </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> Collections.binarySearch(list, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">key</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">用二叉树算法来查找，首先得排序好</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pos=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> pos);<br /><br />        Collections.copy(list, list1); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">把list1复制到list上，原list元素被覆盖</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.fill(list, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ss</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">用"ss"填充list</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.max(list); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">找最大元素</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.reverse(list); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">把排序</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.shuffle(list);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">混乱排序</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000"><br />        Collections.singleton(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ss</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返回一个Set集合，不可改，只有ss一个元素</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.unmodifiableList(list);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返回一个不可改的新的List，原list不变</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.synchronizedList(list);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返回一个同步的新的List，原list不变<br /></span></div></div>
		<br />5、Properties<br />特点：Properties继承自Hashtable，是Map的一个实现。不过它在读取Properties文件方法特别方便<br />示例：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">        Properties p </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> System.getProperties(); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">得到系统属性</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        p.list(System.out);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">打印所有</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000"><br />        </span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000"><br />         * 从user.home=C:\Documents and Settings\chengang<br />         * 读取properties文件填充到Properties<br />         </span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br />        Properties p2 </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> System.getProperties(); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">得到系统属性</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        File file </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> File(p.getProperty(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">user.home</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">), </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">argo.user.properties</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />        p2.load(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> FileInputStream(file));<br />        System.err.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">------------------------------</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />        p2.list(System.out);<br /></span></div><img src ="http://www.blogjava.net/chengang/aggbug/38611.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-04-01 15:48 <a href="http://www.blogjava.net/chengang/archive/2006/04/01/38611.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAAS在Java Web Start中的设置</title><link>http://www.blogjava.net/chengang/archive/2006/03/07/34077.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Tue, 07 Mar 2006 06:53:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/03/07/34077.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/34077.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/03/07/34077.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/34077.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/34077.html</trackback:ping><description><![CDATA[<DIV class=item-content>
<P align=center>文/陈刚 from <A href="http://www.chengang.com.cn/">www.chengang.com.cn</A></P>
<P><STRONG>一、前言</STRONG></P>
<P>　　我这个AdminConsole项目是用Java Web Start（简称JWS）来让用户访问的，后来在用户登录部份用到了JAAS，而JAAS有一个登录配置文件的设定。过去，我一直是在Eclipse的Run里做设置“-Djava.security.auth.login.config=D:\wxxr\login.config”，如下图：<BR><BR><A href="http://blog.sina.com.cn/pic/54bde01c02000043" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c02000043" border=0></A></P>
<P align=left>　　但这只是权宜之计，在将项目从本地以JWS发布到服务器就会碰到两个问题：（1）为了灵活，不能引用绝对地址的（2）在JWS中怎么设定对login.config的引用。<BR><BR>　　JAAS中对配置文件login.config的引用，主要有两种方法：<BR>（1）动态配置：“-Djava.security.auth.login.config=D:\wxxr\login.config”。它其实是java.exe的一个参数，你可以像我一样在Eclipse的run里设置，也可以在命令行运行程序的方式中指定：c:\jdk\bin\java -Djava.security.auth.login.config=D:\wxxr\login.config -jar.......。<BR>（2）在程序里静态配置：System.setProperty("java.security.auth.login.config", "D:\wxxr\login.config");<BR><BR><STRONG>二、JWS中对JAAS动态配置的方法<BR><BR></STRONG>　　在JWS中，如果你想动态配置的，则在JWS的jnlp文件里设置如下：<BR>&nbsp;&lt;resources&gt;<BR>&nbsp;&nbsp;&lt;j2se version="1.4+" href="<A href="http://java.sun.com/products/autodl/j2se">http://java.sun.com/products/autodl/j2se</A>"&nbsp; java-vm-args="-Djava.security.auth.login.config=D:\wxxr\login.config" /&gt;<BR>　........&nbsp;&nbsp;<BR>&nbsp;&lt;/resources&gt;<BR><BR>或者<BR><BR>&nbsp;&lt;resources&gt;<BR>&nbsp;&nbsp;&lt;j2se version="1.4+" href="<A href="http://java.sun.com/products/autodl/j2se">http://java.sun.com/products/autodl/j2se</A>"&nbsp;/&gt;<BR>&nbsp; &lt;property name="java.security.auth.login.config" value="D:\wxxr\login.config"/&gt;<BR>　........&nbsp;&nbsp;<BR>&nbsp;&lt;/resources&gt;<BR><BR>　　上面的设置有一个关键问题：对login.config引用的是绝对地址，这个地址不是指向服务器端的地址，而是客户端的地址。这也就要求客户在D:\wxxr\目录含有login.config文件，显然我们不能对客户有这种麻烦要求（最好就是客户什么都不用做，这也是JWS的存在的价值和目的）。<BR>　　因此这里还有一个变通的方法：把“D:\wxxr\login.config”改成“http://your_website:8080/adminconsole/login.config”，这样就会去网上定位login.config，而不必再把login.config安装在客户端里了。<BR><BR><BR><STRONG>三、JWS中对JAAS静态配置的方法</STRONG><BR><BR>　　在上面的用web url的方法中还是有一点缺陷，login.config将是可以被其他客户轻易看到的，安全性不高。而且服务器的网站名变了以后，还得相应修改jnlp文件。所以我们不妨考虑一下静态配置的方法，用静态配置方法之后，就不用在jnlp文件里配置了，少了不了麻烦。<BR><BR>第一种：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">System.setProperty(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">java.security.auth.login.config</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;URL(BasicServiceImpl.getInstance().getCodeBase(),</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">login.config</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">).toString());</SPAN></DIV></DIV>
<P>说明：<BR>（1）BasicServiceImpl是JDK's javaws.jar包中的类（jdk\jre\javaws\javaws.jar）。<BR>（2）BasicServiceImpl.getInstance().getCodeBase()得到的值是“http://your_website:8080/adminconsole/”，这个还是和前面web url其实一样，只不过它是动态获得web url。至于如何获得服务器的路径的那种，对于普通的java application我没研究过，我只试过下面eclipse RCP的。<BR>（3）你只需要保证<A href="http://your_website:8080/adminconsole/login.config">http://your_website:8080/adminconsole/login.config</A>　能访问到login.config文件即可。<BR><BR>第二种：在Eclipse RCP程序中设置的方法</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">String&nbsp;path&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;AdminConsolePlugin.getDefault().find(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Path(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">properties/login.config</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">)).toString();&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">AdminConsolePlugin就是项目的那***Plugin.java文件，不同的项目会不同。</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">logger.info(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">login.config&nbsp;path=</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;path);　</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">logger是log4j的一个对象，你可以把这一行删除</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">System.setProperty(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">java.security.auth.login.config</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;path);</SPAN></DIV></DIV>
<P>　　path的值有点怪，是“bundleentry://3/properties/login.config”。properties/login.config在服务器上的位置如下图：</P>
<P align=left><A href="http://blog.sina.com.cn/pic/54bde01c02000044" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c02000044" border=0></A><BR>　　注：Eclipse RCP要装在JWS上，还得用一个开源软件WebRCP：<A href="http://sourceforge.net/projects/webrcp">http://sourceforge.net/projects/webrcp</A>。此开源软件简单易用，连文档都不用看。它提供的webrcp-tutorial，本身就是一个RCP使用webrcp的例子，你只需要参照archives\tutorial.zip的目录结构将自己的RCP项目打包，然后用自己项目的zip替换掉archives\tutorial.zip即可。如果你想换一个zip名字，则需要修改tutorial.jsp文件（其实也是一个jnlp）中的“&lt;property name=....&gt;”相应的几项。<BR><BR><BR><STRONG>参考资料：<BR></STRONG><A href="http://forum.java.sun.com/thread.jspa?threadID=612861&amp;tstart=300">http://forum.java.sun.com/thread.jspa?threadID=612861&amp;tstart=300</A><BR><A href="http://forum.java.sun.com/thread.jspa?threadID=621588&amp;messageID=3523625">http://forum.java.sun.com/thread.jspa?threadID=621588&amp;messageID=3523625</A><BR></P>
<DIV class=clear></DIV></DIV><img src ="http://www.blogjava.net/chengang/aggbug/34077.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-03-07 14:53 <a href="http://www.blogjava.net/chengang/archive/2006/03/07/34077.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Web Start简介</title><link>http://www.blogjava.net/chengang/archive/2006/03/07/34076.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Tue, 07 Mar 2006 06:52:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/03/07/34076.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/34076.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/03/07/34076.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/34076.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/34076.html</trackback:ping><description><![CDATA[<P align=center>文/陈刚 from <A href="http://www.chengang.com.cn/">www.chengang.com.cn</A></P>
<P>　　最近由于工作关系，老大嘱咐我看一下Java Web Start。以前安装JDK时，会在“开始”菜单加一个快捷菜单“Java Web Start”，也不知是做什么用的，我一般都是删除。今天从网上查了一下资料，不看不知道，一看吓一跳，觉得这JWS（Java Web Start简称）很象传说中的“服务器端小程序下载运行”。而且JWS很早就有了，我看有些文章资料已经是2002年发的，自己竟然全然不知它的存在，实在是愚昧呀。</P>
<H5>1.&nbsp; JWS有什么用</H5>
<P>　　B/S风行的一个很大原因就是它有部署方便的优势，这是C/S的Application所无法比拟的。现在，JWS让用户可以下载服务器端的Java Application到本机运行，并且没有安装、配置等繁琐的操作。SUN网站上有Demo，大家可以体验一下效果：<A href="http://java.sun.com/products/javawebstart/demos.html">http://java.sun.com/products/javawebstart/demos.html</A>&nbsp; 。</P>
<H5>2.&nbsp; JWS的运行原理</H5>
<P>　　浏览器的运行Java Applica ton的链接指向的不是程序本身，而是一个*.jnlp文件，这个文件包含了Java Application的一些配置信息。然后JWS解读这个文件的信息，将服务器端的Java Application下载到本机上，并运行。</P>
<P>　　当然第一次运行程序时，由于要下载所以速度会稍微慢一些，不过第二次运行时，JWS会自动去服务器上检查是否有新的程序版本发布，如果没有就会直接运行本机已经下载的程序，这就和运行本机Java Application没什么区别了。运行程序之初，JWS还会提示你是否创建一个相应的快捷菜单。</P>
<P>　　程序下载到本机的默认位置是：“C:\Documents and Settings\admin\Application Data\Sun\Java\Deployment\javaws\cache\indirect\indirect12423.ind”，你可以在本机的“JWS应用程序管理器”的里重新设置此存放目录。</P>
<P><A href="http://blog.sina.com.cn/pic/54bde01c0200003g" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c0200003g" border=0></A></P>
<P>　　JWS无疑要比Applet的应用范围更广（据说还得过＊＊的最佳创意奖），它对于布署一些小型的程序应用是非常方便的，但我以为现在还主要适用于局域网。因为一个程序一般约有几十M，如果是Internet用户第一次的下载速度会很慢。</P>
<H5>3.&nbsp; 安全性问题</H5>
<P>　　但和Applet一样，JWS也面临安全性问题，默认情况下JWS对本机磁盘和本地网络的访问是有限制的。如果该程序要越权访问，这时会弹出一个警告框（类似于ActivX的数字签名），用户可以自已决定是否信任该软件，而对其放开限制。</P>
<H5>4.&nbsp; JWS的优缺点</H5>
<P>　　JWS的优点就是让程序的布署更简单，而且用户端的应用可以时刻保持和服务器端的最新版本同步，这为升级版本提供了很大的方便。缺点也是明显的，由于要运行应用必须一次下载所有的程序文件（JWS的jnlp配置文件有个lazy选项，但作用不明显），所以第一次下载速度很慢，不适用于互联网。从这一点来看B/S形式的应用还是有优势的。</P>
<H5>5.&nbsp; 参考资料</H5>
<P><A href="http://www.chinaitlab.com/www/news/article_show.asp?id=25239">http://www.chinaitlab.com/www/news/article_show.asp?id=25239</A><BR><A href="http://blog.csdn.net/emag_java/archive/2005/01/13/252047.aspx">http://blog.csdn.net/emag_java/archive/2005/01/13/252047.aspx</A>&nbsp; </P>
<H3>&nbsp;</H3>
<H3>Java Web Start实例</H3>
<H5>1、示例说明</H5>
<P>　　由于本BLOG现主要以Eclipse和SWT为内容，所以Java Web Start（简称JWS）也以一个SWT应用程序来做为示例。本文用＜Eclipse从入门到精通＞书中打包一章的打包结果为示例，该示例为一个SWT/JFace程序，其打包后的文件结构如下：<BR><A href="http://blog.sina.com.cn/pic/54bde01c0200003h" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c0200003h" border=0></A></P>
<P>说明：&nbsp;</P>
<UL>
<LI>myswt是主包，里面含有自己写的程序代码 
<LI>swt-win32-3063.dll是本地化文件 
<LI>lib子目录下还有三个jar文件：jface.jar、runtime.jar、swt.jar，这三个文件是SWT程序的支持库</LI></UL>
<P>　　如果是在本地运行此程序，双击myswt.jar即可（要求Windows中jar格式的文件默认用javaw.exe打开，如下图所示：<A href="http://blog.sina.com.cn/pic/54bde01c0200003i" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c0200003i" border=0></A></P>
<P>　　现在我们要将这个程序用JWS部署到服务器端，然后编写一个网页，让用户单击网页上的链接就可以下载该SWT程序并运行。</P>
<H5>2、准备工作</H5>
<P>本人的开发环境为：WinodwsXP SP2 ＋ JDK1.4.2 ＋ Tomcat 5.0.28<BR>（1）首先得先安装Tomcat，这一步的操作方法本文省略<BR>（2）在Tomcat的webapps\ROOT路径下创建一个“myswt”目录。在我的电脑上，其绝对路径如下：E:\Program Files\Apache Software Foundation\Tomcat 5.0\webapps\ROOT\myswt。<BR>（3）将前面所述的SWT程序的文件复制到webapps\ROOT\myswt目录中。</P>
<H5>3、生成证书</H5>
<P>创建一个批处理文件：key.bat</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 106.51%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; HEIGHT: 64px; BACKGROUND-COLOR: #eeeeee"><PRE><P class=a0><SPAN lang=EN-US>c:\jdk\bin\keytool -genkey -keystore myKeystore -alias myself</SPAN></P><P class=a0><SPAN lang=EN-US>c:\jdk\bin\keytool -list -keystore myKeystore</SPAN></P><P class=a0><SPAN lang=EN-US>pause</SPAN></P></PRE></DIV>
<P>说明：</P>
<UL>
<LI>keytool是JDK自带的一个工具，用于数字签名。在我的电脑，它是位于c:\jdk\bin\路径下，由于我没有设置环境变量path，所以在批处理文件中硬性指定keytool的路径。如果是自己用或者公司内部用，象本文这样用keytool生成一个自签名的证书也就可以了。但如果你想让签名更正式一些，以获得其他用户的信任，最好去认证中心（如 Thawte 或 VeriSign）获取一个证书。 
<LI>第一句将生成一个证书，文件名：myKeystore 
<LI>第二句是列出密钥证书中的所有入口。（这一句是可选的，只是为了显示出来看一下，不要也行） 
<LI>最后一句是暂停pause，以便批处理完成后，我们可以回顾一下全过程。</LI></UL>
<P>运行批处理key.bat后的全部输入过程如下图所示：</P>
<P><A href="http://blog.sina.com.cn/pic/54bde01c0200003j" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c0200003j" border=0></A></P>
<H5>4、用证用为应用程序签名</H5>
<P>（1）因为签名只认jar包，所以先将swt-win32-3063.dll文件用WinRAR或c:\jdk\bin\jar打一个jar包(swt-win32-3063.jar)。客户端下载后，会自动解开此包，将swt-win32-3063.dll还原到客户端。</P>
<P>注意：如果你用WinRAR打包，在压缩时必须选ZIP格式，不能选RAR格式。</P>
<P>（2）创建一个用于签名的批处理文件：jarsigner.bat，其内容如下：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 118.55%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; HEIGHT: 91px; BACKGROUND-COLOR: #eeeeee"><PRE><P class=a0><SPAN lang=EN-US>c:\jdk\bin\jarsigner -keystore myKeystore myswt.jar myself</SPAN></P><P class=a0><SPAN lang=EN-US>c:\jdk\bin\jarsigner -keystore myKeystore lib\jface.jar myself</SPAN></P><P class=a0><SPAN lang=EN-US>c:\jdk\bin\jarsigner -keystore myKeystore lib\runtime.jar myself</SPAN></P><P class=a0><SPAN lang=EN-US>c:\jdk\bin\jarsigner -keystore myKeystore lib\swt.jar myself</SPAN></P><P class=a0><SPAN lang=EN-US>c:\jdk\bin\jarsigner -keystore myKeystore swt-win32-3063.jar myself</SPAN></P><P class=a0><SPAN lang=EN-US>pause</SPAN></P></PRE></DIV>
<DIV>&nbsp;</DIV>
<DIV>这里每一条命令都要求你输入密码，它就是在创建证书myKeystore时设置的那个密码。至此，签名证书部份完成了，下一步是创建jnlp文件。</DIV>
<DIV>&nbsp;</DIV>
<H5>5、创建jnlp文件</H5>
<DIV>（1）创建一个名为myswt.jnlp的jnlp文件，这个文件是Java Web Start的核心配置文件，其内容如下：</DIV>
<DIV>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 113.7%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; HEIGHT: 332px; BACKGROUND-COLOR: #eeeeee"><PRE>&lt;?xml version="1.0" encoding="GBK"?&gt;<BR>&lt;jnlp codebase="<A href="http://localhost:8080/myswt">http://localhost:8080/myswt</A>"&gt;<BR>&nbsp;&lt;information&gt;<BR>&nbsp;&nbsp;&lt;title&gt;子在川曰(<A href="http://blog.csdn.net/glchengang)</title">http://blog.csdn.net/glchengang)&lt;/title</A>&gt;<BR>&nbsp;&nbsp;&lt;vendor&gt;陈刚&lt;/vendor&gt;<BR>&nbsp;&nbsp;&lt;offline-allowed/&gt;<BR>&nbsp;&lt;/information&gt;<BR>&nbsp;&lt;security&gt;<BR>&nbsp;&nbsp;&lt;all-permissions/&gt;<BR>&nbsp;&lt;/security&gt;<BR>&nbsp;&lt;resources&gt;<BR>&nbsp;&nbsp;&lt;j2se version="1.4+"/&gt;<BR>&nbsp;&nbsp;&lt;jar href="myswt.jar"/&gt;<BR>&nbsp;&nbsp;&lt;jar href="lib/jface.jar"/&gt;<BR>&nbsp;&nbsp;&lt;jar href="lib/runtime.jar"/&gt;<BR>&nbsp;&nbsp;&lt;jar href="lib/swt.jar"/&gt;<BR>&nbsp;&nbsp;&lt;nativelib href="swt-win32-3063.jar"/&gt;<BR>&nbsp;&lt;/resources&gt;<BR>&nbsp;&lt;application-desc main-class="jface.dialog.wizard.WizardDialog1"/&gt;<BR>&lt;/jnlp&gt;<BR></PRE></DIV></DIV>
<DIV>&nbsp;</DIV>
<DIV>说明：</DIV>
<UL>
<LI>encoding="GBK"&nbsp; 本文选择了GBK，一般来说应该用UTF-8。我在这里之所以选择GBK字符集，主要是为了演示示例方便，如果是正式应用，还是应该改为UTF-8。如果用UTF－8，则该文件的中文要转换成UNICODE码，否则实际运行时将显示乱码，你可以用c:\jdk\bin\native2ascii.exe来进行“汉字－＞UNICODE”的转换。 
<LI>codebase="<A href="http://localhost:8080/myswt">http://localhost:8080/myswt</A>" 本应用程序的URL 
<LI>&lt;information&gt;项，是一些显示信息，&lt;title&gt;、&lt;vendor&gt;都是必选的。&lt;offline-allowed/&gt;是可选的，它表示允许应用程序脱机运行（不和服务器联网）。 
<LI>&lt;security&gt;项是指开放用户本机的所有权限给应用程序，这一项会导致弹出一个数字签名对话框。 
<LI>&lt;resources&gt;列出了用户需要下载的资源。&lt;j2se version="1.4+"/&gt;是指，要求用户本机安装Java1.4以上版本。&lt;nativelib&gt;是指此包含有本地文件，这时JWS下载后会将此包解开。 
<LI>&lt;application-desc&gt;指定了程序的入口类，你也可以指定其他的入口类，它不受限制。jface.dialog.wizard.WizardDialog1是myswt.jar包中的一个向导式对话框，这是我自己编写的一个SWT程序。</LI></UL>
<P>（2）创建一个HTML网页，网页指向jnlp文件。我们给此HTML网页取名：test.html，其内容如下：</P>
<DIV>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; HEIGHT: 27px; BACKGROUND-COLOR: #eeeeee"><PRE><SPAN lang=EN-US>&lt;A HREF="myswt.jnlp"&gt;</SPAN><SPAN style="FONT-FAMILY: 'Courier New'">启动</SPAN><SPAN lang=EN-US>&lt;/A&gt;</SPAN></PRE></DIV></DIV>
<H5>6、最后效果</H5>
<P>（1）最后的服务器的目录结构如下图所示：</P>
<P><A href="http://blog.sina.com.cn/pic/54bde01c0200003k" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c0200003k" border=0></A></P>
<P>（2）用浏览器浏览：<A href="http://localhost:8080/myswt/test.html">http://localhost:8080/myswt/test.html</A></P>
<P><A href="http://blog.sina.com.cn/pic/54bde01c0200003l" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c0200003l" border=0></A></P>
<P>单击“启动”后出现下图，开始从服务器上下载SWT应用程序：</P>
<P><A href="http://blog.sina.com.cn/pic/54bde01c0200003m" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c0200003m" border=0></A><A href="http://blog.sina.com.cn/pic/54bde01c0200003n" target=_blank></A></P>
<P>下载完成后，出现如下图，提示用户是否向应用程序开放本机所有权限（弹出这个对话框是由jnlp文件中的&lt;security&gt;项设置决定的）。</P><A href="http://blog.sina.com.cn/pic/54bde01c0200003n" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c0200003n" border=0></A> 
<P>单击“启动”按钮，将运行程序，出现下图。（附注：这里没有弹出提示你添加快捷菜单的对话框）</P>
<P><A href="http://blog.sina.com.cn/pic/54bde01c0200003o" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c0200003o" border=0></A></P>
<P>&nbsp;</P>
<H5><SPAN lang=EN-US>7、其他注意事项</SPAN></H5>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US>1</SPAN><SPAN style="FONT-FAMILY: 宋体">）如果单击网页的“启动”链接时，显示的是</SPAN><SPAN lang=EN-US>jnlp</SPAN><SPAN style="FONT-FAMILY: 宋体">文件的内容，还非下载服务器的应用程序。这时你需要做如下检查：</SPAN></P>
<UL>
<LI>
<DIV class=MsoNormal><SPAN style="FONT-FAMILY: 宋体"></SPAN><SPAN lang=EN-US style="FONT-SIZE: 7.5pt; FONT-FAMILY: Wingdings"><SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;</SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">在</SPAN><SPAN lang=EN-US>Windows</SPAN><SPAN style="FONT-FAMILY: 宋体">中，</SPAN><SPAN lang=EN-US>jnlp</SPAN><SPAN style="FONT-FAMILY: 宋体">格式的文件应该默认用</SPAN><SPAN lang=EN-US>javaw</SPAN><SPAN style="FONT-FAMILY: 宋体">打开。如果你把它改变成了用记事本或其他程序打开，就也会出错。</SPAN></DIV>
<LI>
<DIV class=MsoNormal><SPAN style="FONT-FAMILY: 宋体"></SPAN><SPAN lang=EN-US>WEB</SPAN><SPAN style="FONT-FAMILY: 宋体">服务器是否能否辨识</SPAN><SPAN lang=EN-US>jnlp</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>jar</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>class</SPAN><SPAN style="FONT-FAMILY: 宋体">文件的格式。如果你是用</SPAN><SPAN lang=EN-US>Tomcat</SPAN><SPAN style="FONT-FAMILY: 宋体">，可以打开</SPAN><SPAN lang=EN-US>conf</SPAN><SPAN style="FONT-FAMILY: 宋体">目录的</SPAN><SPAN lang=EN-US>WEB.XML</SPAN><SPAN style="FONT-FAMILY: 宋体">文件检查一下。一般来说，较新的</SPAN><SPAN lang=EN-US>WEB</SPAN><SPAN style="FONT-FAMILY: 宋体">服务器都支持</SPAN><SPAN lang=EN-US>jnlp</SPAN><SPAN style="FONT-FAMILY: 宋体">，如果</SPAN><SPAN lang=EN-US>Tomcat</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>WebLogic</SPAN><SPAN style="FONT-FAMILY: 宋体">等（微软的</SPAN><SPAN lang=EN-US>IIS</SPAN><SPAN style="FONT-FAMILY: 宋体">不支持</SPAN><SPAN lang=EN-US>Java</SPAN><SPAN style="FONT-FAMILY: 宋体">，当然也不可能支持</SPAN><SPAN lang=EN-US>jnlp</SPAN><SPAN style="FONT-FAMILY: 宋体">，我是这么想的没去测试过）。如果不支持，就在</SPAN><SPAN lang=EN-US>WEB</SPAN><SPAN style="FONT-FAMILY: 宋体">服务器的配置文件里加上下面的内容。</SPAN></DIV></LI></UL><SPAN style="FONT-FAMILY: 宋体">
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 97.98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; HEIGHT: 272px; BACKGROUND-COLOR: #eeeeee"><PRE>&lt;mime-mapping&gt;<BR>&nbsp;&lt;extension&gt;class&lt;/extension&gt;<BR>&nbsp;&lt;mime-type&gt;application/java&lt;/mime-type&gt;<BR>&lt;/mime-mapping&gt;</PRE><PRE>&lt;mime-mapping&gt;<BR>&nbsp;&lt;extension&gt;jar&lt;/extension&gt;<BR>&nbsp;&lt;mime-type&gt;application/java-archive&lt;/mime-type&gt;<BR>&lt;/mime-mapping&gt;<BR>&nbsp;<BR>&lt;mime-mapping&gt;<BR>&nbsp;&lt;extension&gt;jnlp&lt;/extension&gt;<BR>&nbsp;&lt;mime-type&gt;application/x-java-jnlp-file&lt;/mime-type&gt;<BR>&lt;/mime-mapping&gt;</PRE></DIV></SPAN>
<P class=CharChar><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US>2</SPAN><SPAN style="FONT-FAMILY: 宋体">）在使用</SPAN><SPAN lang=EN-US>Java Web Start</SPAN><SPAN style="FONT-FAMILY: 宋体">的时候可能会出现</SPAN><SPAN lang=EN-US>"</SPAN><SPAN style="FONT-FAMILY: 宋体">下载资源错误</SPAN><SPAN lang=EN-US>"</SPAN><SPAN style="FONT-FAMILY: 宋体">，大致的出错信息如下：</SPAN></SPAN></P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-FAMILY: 宋体">
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><PRE>JNLPException[category: Download Error : Exception:<BR>&nbsp;&nbsp; java.io.IOException:<BR>&nbsp;&nbsp; rename failed in cache : LaunchDesc: null ] at..... </PRE></DIV></SPAN></SPAN>
<DIV>&nbsp;</DIV>
<DIV>　　这个错误的原因是因为每次调用Java Web Start都会到server上查找程序是否更新，然后将程序下载到本地的java web start目录下的cache目录中，如果cache中已经有同名文件，而且该文件正在被使用，那么新下载的文件就会出现 rename failed错误，而且手工去删除本地的文件还会报错：文件正被使用！</DIV>
<DIV>&nbsp;</DIV>
<DIV>　　这里涉及到Java Web Start中的sign机制，可能对每个jar文件都需要标记，有的时候会在任务管理器中看到javaw.exe在运行，将该程序终止后就可以将本地的jar文件删除掉，说明这些本地文件可能还保留着文件锁定吧！有时即使将Task Manager中将所有的java程序都kill掉还是会出错，必须要注销windows才可以，不知道是不是Java Web Start</DIV>
<DIV>&nbsp;</DIV>
<DIV>（3）如果需要给*.jar文件传递参数，可以用如下代码：</DIV>
<DIV>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><PRE>&lt;application-desc main-class="XBFrame"/&gt;<BR>&nbsp;&lt;argument&gt;-port&lt;/argument&gt;<BR>&nbsp;&lt;argument&gt;1008&lt;/argument&gt;&nbsp; "注意-port和1008是两个参数，要分开写<BR>&lt;/application-desc&gt;</PRE></DIV></DIV>
<DIV>&nbsp;</DIV>
<DIV>（4）有的时候还需要看到*.jar中System.out.print语句输出的信息，就要打开jws的console，可以在jws manager 中的首选项中设置（附注：（2）、（3）、（4）照抄＜＜java web start实现关键问题(二)＞＞一文）</DIV>
<DIV>&nbsp;</DIV>
<DIV>（5）如果出现失败，最基本的查错手段就是看看出错的“详细信息”，如下图所示。</DIV>
<DIV><A href="http://blog.sina.com.cn/pic/54bde01c0200003p" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c0200003p" border=0></A></DIV>
<DIV>&nbsp;</DIV>
<DIV>单击“详细信息”按钮，出现下图</DIV>
<DIV><A href="http://blog.sina.com.cn/pic/54bde01c0200003q" target=_blank><IMG src="http://blog.sina.com.cn/pic/54bde01c0200003q" border=0></A></DIV>
<DIV>&nbsp;</DIV>
<H5>参考资料</H5>
<DIV><A href="http://www-900.ibm.com/developerWorks/cn/java/j-webstart/index.shtml">http://www-900.ibm.com/developerWorks/cn/java/j-webstart/index.shtml</A></DIV>
<DIV><A href="http://www-900.ibm.com/developerWorks/cn/linux/opensource/os-jws/index.shtml">http://www-900.ibm.com/developerWorks/cn/linux/opensource/os-jws/index.shtml</A></DIV>
<DIV><A href="http://www-900.ibm.com/developerWorks/cn/java/l-webstart/index.shtml#author1">http://www-900.ibm.com/developerWorks/cn/java/l-webstart/index.shtml#author1</A></DIV>
<DIV><A href="http://dev.csdn.net/article/14/14216.shtm">http://dev.csdn.net/article/14/14216.shtm</A>&nbsp;学用Java Web Start 部署应用程序</DIV>
<DIV><A href="http://ecolab.ruc.edu.cn/new/Article_Show.asp?ArticleID=80">http://ecolab.ruc.edu.cn/new/Article_Show.asp?ArticleID=80</A>&nbsp;关于java的数字签名</DIV>
<DIV><A href="http://www.51one.net/info/3291681715538397.htm">http://www.51one.net/info/3291681715538397.htm</A>&nbsp;java web start实现关键问题(二)</DIV>
<DIV>&nbsp;</DIV>
<H5>作者简介</H5>
<DIV>陈刚，广西桂林人，著作有《Eclipse从入门到精通》<BR>您可以通过其博客了解更多信息和文章：<A href="http://www.chengang.com.cn/"><FONT color=#000033>http://www.chengang.com.cn</FONT></A></DIV><img src ="http://www.blogjava.net/chengang/aggbug/34076.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-03-07 14:52 <a href="http://www.blogjava.net/chengang/archive/2006/03/07/34076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在JAVA中如何检查字符串日期的合法性</title><link>http://www.blogjava.net/chengang/archive/2006/03/07/34067.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Tue, 07 Mar 2006 06:39:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/03/07/34067.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/34067.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/03/07/34067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/34067.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/34067.html</trackback:ping><description><![CDATA[文/陈刚 from <A href="http://www.chengang.com.cn/">www.chengang.com.cn</A>&nbsp;2005-11-04&nbsp;<BR><BR><BR>
<DIV>　　在SWT中还没有日期控件，所以我的日期是用文本框手工输入的，这时就需要验证输入的日期是否合法。在之前我是复制很久以前写的一段代码，它的解决方法是分解日期字串，然后检查，这很笨且不严格。正确的方案应该是利用DateFormat类来检查，如下所示：<BR>&nbsp;<BR>public final class StringUtil {<BR>&nbsp;&nbsp;&nbsp; private static Calendar calendar = Calendar.getInstance();<BR>&nbsp;&nbsp;&nbsp; private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");<BR>&nbsp;&nbsp;&nbsp; private static DateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");<BR>&nbsp;&nbsp;&nbsp; static {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dateFormat.setLenient(false);//这个的功能是不把1996-13-3 转换为1997-1-3<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dateTimeFormat.setLenient(false);<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp; public static Date parseStringToDate(String dateStr) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (dateStr == null || dateStr.trim().equals(""))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dateStr = dateStr.trim(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Date date = null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (dateStr.length() &lt;= 10) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; date = dateFormat.parse(dateStr);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; date = dateTimeFormat.parse(dateStr);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (Exception e) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new IllegalArgumentException("你输入的日期不合法，请重新输入");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return date;<BR>&nbsp;&nbsp;&nbsp; }<BR>}</DIV>
<DIV><BR>&nbsp;<BR>这个方法的Test Case也一并给出如下：<BR>&nbsp;<BR>public class TestStringUtil extends TestCase {<BR>&nbsp;&nbsp;&nbsp; public void testParseStringToDate() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calendar c = Calendar.getInstance();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.clear();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.set(2000, 1, 3, 0, 0, 0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Date d = StringUtil.parseStringToDate("2000-02-03");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertEquals(c.getTime().getTime(), d.getTime());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calendar c = Calendar.getInstance();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.clear();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.set(2000, 1, 3, 11, 22, 33);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Date d = StringUtil.parseStringToDate("2000-02-03 11:22:33");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertEquals(c.getTime().getTime(), d.getTime());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calendar c = Calendar.getInstance();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.clear();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.set(2000, 1, 3, 0, 0, 0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Date d = StringUtil.parseStringToDate("2000-02-3");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertEquals(c.getTime().getTime(), d.getTime());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calendar c = Calendar.getInstance();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.clear();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.set(2000, 1, 3, 1, 2, 3);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Date d = StringUtil.parseStringToDate("2000-02-03 1:02:03");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertEquals(c.getTime().getTime(), d.getTime());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertNull(StringUtil.parseStringToDate(""));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertNull(StringUtil.parseStringToDate("&nbsp; "));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertNull(StringUtil.parseStringToDate(null));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; public void testParseStringToDateException() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testParseStringToDateException("2000");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testParseStringToDateException("2000-13-03");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testParseStringToDateException("2000-02-03 51:02:03");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testParseStringToDateException("2000-02-03 01:f2:03");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testParseStringToDateException("2000-02-03 01:02");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testParseStringToDateException("2000-02-03 01:02:222");<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; private void testParseStringToDateException(String dateStr) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringUtil.parseStringToDate(dateStr);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fail("末抛出异常");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (Exception e) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertTrue(true);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>}<BR></DIV><img src ="http://www.blogjava.net/chengang/aggbug/34067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-03-07 14:39 <a href="http://www.blogjava.net/chengang/archive/2006/03/07/34067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何删除JAVA集合中的元素</title><link>http://www.blogjava.net/chengang/archive/2006/03/02/33195.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Thu, 02 Mar 2006 06:02:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/03/02/33195.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/33195.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/03/02/33195.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/33195.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/33195.html</trackback:ping><description><![CDATA[文/陈刚　2005-12-05 <br /><br />经常我们要删除集合中的某些元素。有些可能会这么写。 
<div></div><div>    </div><div><div style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px">　　public void operate(List list){<br />        for (Iterator it = list.iterator(); it.hasNext();) {<br />            String str =  (String)it.next();<br />            if (str.equals("chengang")){<br />                list.remove(str);<br />            }<br />        }<br />    }</div></div><div>　　　</div><div>　　这种写法一运行就会报如下异常：</div><div>　</div><div><div style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px">Exception in thread "main" java.util.ConcurrentModificationException<br /> at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449)</div></div><div>　</div><div>　　因为list在循环中的时候是不可以删除它的元素的。后来我是这样做的，一种很笨的方法，思路是这样的：创建一个List专门存放要被删除的元素，循环过后，用List.removeAll方法把元素删除。代码如下：</div><div></div><div><div style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px">    public void operate(List list){<br />        List removeList= new ArrayList();<br />        for (Iterator it = list.iterator(); it.hasNext();) {<br />            String str =  (String)it.next();<br />            if (str.equals("chengang")){<br />                removeList.add(str);<br />            }<br />        }<br />        list.removeAll(removeList);<br />    }</div>　</div><div>　　这样也确实可以解决问题了，但是方法实在太笨重，其实可以有更简单的更高效的方法，就是用Iterator.remove方法，如下：</div><div><div></div><div><div style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px">        for (Iterator it = list.iterator(); it.hasNext();) {<br />            String str =  (String)it.next();<br />            if (str.equals("chengang")){<br />                it.remove();<br />            }<br />        }</div></div><div> </div></div><div>　所以，你对Java的基础知识了解越多，代码就会写得越简洁。相反如果你的代码特别复杂，则方法或设计一定有问题。</div><img src ="http://www.blogjava.net/chengang/aggbug/33195.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-03-02 14:02 <a href="http://www.blogjava.net/chengang/archive/2006/03/02/33195.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDK5.0新特性之：其他</title><link>http://www.blogjava.net/chengang/archive/2006/03/02/33193.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Thu, 02 Mar 2006 05:59:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/03/02/33193.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/33193.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/03/02/33193.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/33193.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/33193.html</trackback:ping><description><![CDATA[<STRONG>文/陈刚　2005-11-26</STRONG>&nbsp; <BR><BR><STRONG>一、自动装箱与拆箱</STRONG>
<P>　　这是一个很体帖的改进。在JDK5.0以前我们常看到下面的代码。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vector v=new Vector();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v.add(new Integer(1));</P>
<P>　　因为Vector.add只接受对象，而1不是对象，所以我们还得把整数１装箱到Integer对象里，真麻烦:(　。现在我们可以这样了，是不是方便许多呢？如下：</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vector&lt;Integer&gt; v=new Vector&lt;Integer&gt;(1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v.add(1);<BR></P>
<P><STRONG>二、新的for循环</STRONG></P>
<P>　　在前面讲枚举的时候已经用到了，再把进面的代码粘贴一次吧，如下：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Color[] colors = Color.values();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (Color c : colors) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("color value=" + c.getColorValue());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</PRE></DIV>
<P>　　注意：不要以为Color[]是数组，就以为for-each循环只适用于数组，对于集合（List、Set)一样可以的，如下：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;String&gt; list = new ArrayList&lt;String&gt;();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (String str : list) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(str);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR></PRE></DIV>
<P></P>
<P><STRONG>三、参数个数的可变性</STRONG></P>
<P>　　参数的个数是可变的，如下代码中的test方法就是一个int型的可变参数，当然你可以将参数设成String、Object等。</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>public class Test {<BR>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test(1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test(2, 3, 4);<BR>&nbsp;&nbsp;&nbsp; }</PRE><PRE>&nbsp;&nbsp;&nbsp; public static void test(int... ints) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i : ints) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(i);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>}</PRE></DIV>
<P><STRONG>四、静态引用</STRONG></P>
<P>　　什么是静态引用，先看下面的代码：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>package jdk5;<BR>public class Model {<BR>&nbsp;&nbsp;&nbsp; public static void operate() {}<BR>&nbsp;&nbsp;&nbsp; public static String ABC;<BR>}</PRE></DIV>
<P>Model类有一个静态方法operate和一个静态变量（必须是静态的），这是一个很普通的类。而下面的Test类就有些奇怪了：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>package jdk5;</PRE><PRE>import static jdk5.Model.ABC;<BR>import static jdk5.Model.operate;</PRE><PRE>public class Test {<BR>&nbsp;&nbsp;&nbsp; public static void test() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; operate();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s = ABC;<BR>&nbsp;&nbsp;&nbsp; }<BR>}</PRE></DIV>
<P>有那些奇怪的地方呢？</P>
<P>（１）import 后面多了一个static<BR>（２）jdk5.Model后面多写了方法operate和变量ABC</P>
<P>　　有了上面奇怪的写法之后，以后在Test类中要使用import static的方法、变量就可以象本地方法和变量一样用了。</P>
<P></P>
<P><STRONG>五、C风格格式化输出</STRONG></P>
<P>　　以前我们在这里写代码：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int x = 10;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int y = 20;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int sum = x + y;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.printf(x + " + " + y + " = " + sum);<BR>&nbsp;&nbsp;&nbsp; }</PRE></DIV>
<P>　　在JDK5.0后，我们这样写代码：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int x = 10;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int y = 20;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int sum = x + y;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.printf("%d + %d = %d", x, y, sum);<BR>&nbsp;&nbsp;&nbsp; }</PRE></DIV>
<P>　　两段代码的效果都是一样的“10 + 20 = 30”，但第二种C风格的写法显示方便易读多了。</P>
<P></P>
<P><STRONG>六、元数据（注解）</STRONG></P>
<P>　　这是JDK5.0学XDoclt的，有了注解，以后我们可以不必写接口，EJB写起来会方便很多。EJB3.0要精简写法，注解要占一些功劳。</P>
<P>　　介绍一个常用的注解：@Override，示例如下：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>public class Test extends ATest{<BR> <BR>    @Override<BR>&nbsp;&nbsp;&nbsp; public void test() {<BR>&nbsp;&nbsp;&nbsp; }<BR>}</PRE></DIV>
<P>　在方法前加了这个注解，就限定死了Test的这个方法一定要是覆盖自ATest的方法test，否则就会报错。比如你不心把方法test()写成了tesd()，编译时就会报错。另一个要注意的是@Override用于定义覆盖接口的方法，也就是说ATest必须是一个抽象类、普通类，但不能是接口。</P>
<P>&nbsp;&nbsp; 另一个常见到的注解是@Deprecated，表明该项（类、字段、方法）不再被推荐使用。不过我们自己一般很少用到这个注解。</P>
<P>　　好了，注解只讲这两个吧，也不必了解太多，知道个概念，以后用到的时候再说吧。关于注解，建议看看XDoclt，这是一个开源小工具，在项目开发中非常好用。</P>
<P><STRONG></STRONG></P>
<P><STRONG>作者简介</STRONG></P>
<P>陈刚，广西桂林人，著作有《Eclipse从入门到精通》<BR>您可以通过其博客了解更多信息和文章：<A href="http://www.chengang.com.cn/"><FONT color=#000033>http://www.chengang.com.cn</FONT></A> </P><img src ="http://www.blogjava.net/chengang/aggbug/33193.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-03-02 13:59 <a href="http://www.blogjava.net/chengang/archive/2006/03/02/33193.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDK5.0新特性之：泛型</title><link>http://www.blogjava.net/chengang/archive/2006/03/02/33191.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Thu, 02 Mar 2006 05:55:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/03/02/33191.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/33191.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/03/02/33191.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/33191.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/33191.html</trackback:ping><description><![CDATA[<DIV class=item-content>
<P><STRONG>文/陈刚 2005-11-09&nbsp;<BR><BR>一、前言</STRONG></P>
<P>　　泛型这个词在现在的JAVA挺时髦，光从字面上你是无法知道它代表些什么东东的，所以我们还是不要从字面去理解，而是从一些实例去了解它吧。</P>
<P><STRONG>二、泛型之前的日子</STRONG></P>
<P>　　ＪＤＫ１.4之前是没有泛型的概念的，所以我们才会有下面的代码:</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>        List list = new ArrayList();<BR>        list.add("aaaa");<BR>        list.add("bbbb");<BR>        list.add("cccc");</PRE><PRE>        for (Iterator it = list.iterator(); it.hasNext();) {<BR>            String str = (String) it.next();<BR>            System.out.println(str);<BR>        }</PRE></DIV>
<P>　　上面是一段很平常的代码，在一个List集合加入一些字符串，然后再用一个遍历循环把它打印出来。“String str = (String) it.next()”这一句我们可以看到List取出值都是Object，所以我们要得String型，还要做一个类型转换，真是麻烦。更麻烦的是list.add(Object obj)的参数是Object类型，所以如果我们一不小心把list.add("cccc");写成list.add(new Integer(76));程序在循环打印的类型转换中就会出错。</P>
<P>　　问题：我们能不能让add方法只认String型呢？<BR>　　回答：可以！用JDK5.0的泛型。</P>
<P><STRONG>三、泛型后的幸福生活</STRONG></P>
<P>　　JAVA有了泛型后，就象十年的老光棍讨了老婆，那个好处自不待言。我们来看看上面的例子改成泛型的写法是怎么样的：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>        List&lt;String&gt; list = new ArrayList&lt;String&gt;();<BR>        list.add("aaaa");<BR>        list.add("bbbb");<BR>        list.add("cccc");</PRE><PRE>        for (Iterator&lt;String&gt; it = list.iterator(); it.hasNext();) {<BR>            String str=it.next();<BR>            System.out.println(str);<BR>        }</PRE></DIV>
<P>　　看到差别了吗？泛型其实很简单，就是在定义类型的后面加上"&lt;类型&gt;"这样子的声明就行了，它主要还有以下差别：</P>
<UL>
<LI>list.add方法只能接受String类型。list.add(new Integer(76))这样的语句不需要运行程序，在编译时就会检查通不过。 
<LI>it.next()的返回值不再是Object，而变成了String</LI></UL>
<P>　　当然我们其实在循环部份也可以象下面这么写，是不是简洁了很多呢 :-)</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>        List&lt;String&gt; list = new ArrayList&lt;String&gt;();<BR>        list.add("aaaa");<BR>        list.add("bbbb");<BR>        list.add("cccc");</PRE><PRE>        for (String str : list) {<BR>            System.out.println(str);<BR>        }</PRE></DIV>
<P>　　当然需要说明的是，List不仅可以List&lt;String&gt;，也可以是List&lt;Integer&gt;等等其他任何类型。</P>
<P><STRONG>四、更深入了解泛型</STRONG></P>
<P>（１）层层推进的泛型声明</P>
<P>　　“List&lt;List&gt; list;”表示什么呢？就是只接收List型的参数，比如：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;List&gt; list = new ArrayList&lt;List&gt;();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new ArrayList());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new Vector());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new LinkedList());</PRE></DIV>
<P>　　这里要注意List是接口，ArrayList、Vector、LinkedList都是这一接口下的实现类。下面这个有点怪异了，“List&lt;List&lt;String&gt;&gt; list;”表示它只接受List型的参数，而且这种List型的参数又是只是只接受String型，有点层层推进的味道在里面了。</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;List&lt;String&gt;&gt; list = new ArrayList&lt;List&lt;String&gt;&gt;();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new ArrayList&lt;String&gt;());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new Vector&lt;String&gt;());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new LinkedList&lt;String&gt;());</PRE></DIV>
<P><STRIKE></STRIKE></P>
<P></P>
<P></P>
<P>（２）使用泛型上限通通配符：extends </P>
<P>　　这里要着重强调一点：变量的泛型声明和方法的参数的泛型声明有很大差别。</P>
<P>　　变量声明成某类型，同时也可以接受它的子类。比如说Integer、Long、Float都是抽象类Number的子类，所以下面的代码一点问题也没有：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;Number&gt; list = new ArrayList&lt;Number&gt;();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new Integer(1));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new Long(1));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new Float(1.2));<BR></PRE></DIV>
<P>　　但如果换成方法参数的泛型声明则要严格得多了：子类也是不行的。比如下面的代码就是<STRONG><FONT color=#ff0000>错误</FONT></STRONG>的，因为printList参数只接受Number值的List，就是是Number子类的Integer值的List也不行。</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new Integer(1));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new Integer(2));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printList(list);<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; private static void printList(List&lt;Number&gt; list){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (Number num : list) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(num);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR></PRE></DIV>
<P>　上面代码修改的方法有两个，如下</P>
<P>修改方法一：改变量的泛型声明<BR>　　将　List&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;();<BR>　　改为　List&lt;Number&gt; list = new ArrayList&lt;Number&gt;();</P>
<P>修改方法二：用界限通配符改方法参数的泛型声明<BR>　　将　printList(List&lt;Number&gt; list)<BR>　　改为　printList(List&lt;? extends Number&gt; list)<BR>　　说明：extends 的含义就是表示参数可以接受Number型的子类。</P>
<P></P>
<P>（３）使用泛型下限通通配符：super </P>
<P>&nbsp;&nbsp; 　在上限就有下限，下限行就是super，用法和extends一样，含义则和extends相反。比如printList(List&lt;? super Integer&gt; list)表示参数可以接受Integer型及Integer型的超类，即Number了，当然也包括Object这个顶级类。</P>
<P>（４）配置符：？</P>
<P>　　？表示可以接受任何类型，不过我觉得它用得不多，因为printList(List&lt;?&gt; list)和printList(List list)的作用是一样的。</P>
<P></P>
<P><STRONG>五、创建一个支持泛型的类</STRONG></P>
<P>（１）创建一个泛型的类</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>public class Point&lt;T&gt; {<BR>&nbsp;&nbsp;&nbsp; T x;<BR>&nbsp;&nbsp;&nbsp; T y;</PRE><PRE>&nbsp;&nbsp;&nbsp; public T getX() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return x;<BR>&nbsp;&nbsp;&nbsp; }</PRE><PRE>&nbsp;&nbsp;&nbsp; public T getY() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return y;<BR>&nbsp;&nbsp;&nbsp; }</PRE><PRE>&nbsp;&nbsp;&nbsp; public void setX(T x) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.x = x;<BR>&nbsp;&nbsp;&nbsp; }</PRE><PRE>&nbsp;&nbsp;&nbsp; public void setY(T y) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.y = y;<BR>&nbsp;&nbsp;&nbsp; }<BR>}</PRE></DIV>
<P>　　使用这个类的代码如下：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point&lt;Integer&gt; p = new Point&lt;Integer&gt;();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.setX(new Integer(1));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.setY(new Integer(2));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point&lt;String&gt; b = new Point&lt;String&gt;();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.setX("1");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.setY("2");</PRE></DIV>
<P>　　说明：在Point&lt;T&gt;的定义中，T并非关键字，你也可以这样定义Point&lt;ABC&gt;，当然一般还是写T吧，简单也规范。</P>
<P>（２）泛型类的继承与实现</P>
<P>　　java.util.Comparator类是JDK里用来排序的，其源代码如下：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 85px"><PRE>package java.util;<BR>public interface Comparator&lt;T&gt; {<BR>&nbsp;&nbsp;&nbsp; int compare(T o1, T o2);<BR>&nbsp;&nbsp;&nbsp; boolean equals(Object obj);<BR>}</PRE></DIV>
<P>&nbsp;&nbsp; 一个实现此接口的类如下：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 85px"><PRE>&nbsp;&nbsp;&nbsp; public class MyComparator&lt;T&gt; implements Comparator&lt;ObjectInstance&gt; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int compare(ObjectInstance o1, ObjectInstance o2) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s1 = o1.getObjectName().getCanonicalName();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s2 = o2.getObjectName().getCanonicalName();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return s1.compareToIgnoreCase(s2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }</PRE></DIV>
<P>　　说明：ObjectInstance可能大家还太明白，这是我实际项目中的一段代码（关于ＪＭＸ的），ObjectInstance全称javax.management.ObjectInstance。MyComparator的使用代码如下：</P>
<P></P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px">Set set = ......（省略）<BR>List&lt;ObjectInstance&gt; mbeans = new ArrayList&lt;ObjectInstance&gt;(set);<BR>Collections.sort(mbeans, new MyComparator&lt;ObjectInstance&gt;());<BR></DIV>
<P></P>
<P><STRONG>六、最后的感言</STRONG></P>
<P>　　JAVA有了泛型就象老光棍讨了老婆，好处大大的，但和女人一样麻烦也跟着来了：它的严格类型检查，使隐藏的ＢＵＧ更少。有些地方确实也使代码简洁了，有些地方却会使得代码更复杂。所以运用之妙在于是否用得适当，尽量把泛型往简单里用，别越搞越复杂了。&nbsp;</P>
<P><STRONG>参考资料</STRONG></P>
<P>J2SE 5.0中的泛型　<A href="http://www.matrix.org.cn/resource/article/43/43634_java_generics.html">http://www.matrix.org.cn/resource/article/43/43634_java_generics.html</A> </P>
<H5><FONT size=3>作者简介</FONT></H5>
<P>陈刚，广西桂林人，著作有《Eclipse从入门到精通》<BR>您可以通过其博客了解更多信息和文章：<A href="http://www.ChenGang.com.cn"><FONT color=#000033>http://www.ChenGang.com.cn</FONT></A> </P>
<DIV class=clear></DIV></DIV><img src ="http://www.blogjava.net/chengang/aggbug/33191.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-03-02 13:55 <a href="http://www.blogjava.net/chengang/archive/2006/03/02/33191.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDK5.0新特性之：枚举</title><link>http://www.blogjava.net/chengang/archive/2006/03/02/33189.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Thu, 02 Mar 2006 05:53:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/03/02/33189.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/33189.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/03/02/33189.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/33189.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/33189.html</trackback:ping><description><![CDATA[<DIV class=item-content>
<P></P>
<P><STRONG>文/陈刚 2005-11-09&nbsp;<BR><BR>一、前言</STRONG></P>
<P>　　JDK5.0出来有快一年了吧，泛泛的浏览过一些资料，不知道是文章写得生涩，还是我愚笨，总之是没太明白。反正所做的项目也没有用到，所以放在了一边。近来公司平台升级到JBOSS4和JDK5，看来要仔佃看它一看看。上网搜索了一些资料，花了两小时阅读，算明白了一些，好象也不是很难。现将心得和理解结集成文，以便后来者。</P>
<P>　　JDK5.0主要有哪些新特性呢？如下列表</P>
<UL>
<LI>泛型 
<LI>增强的for循环 
<LI>自动装箱和自动拆箱 
<LI>类型安全的枚举 
<LI>可变长度参数 
<LI>静态引入 
<LI>元数据（注解） 
<LI>C风格的格式化输出 </LI></UL>
<P>　　本文先讲“类型安全的枚举”。</P>
<P><STRONG>二、旧的历史</STRONG></P>
<P>　　举个例：有一个如下的“花(flower)”类，它有一个颜色(color)属性，用int型来表示其颜色。</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>public class Flower {<BR>&nbsp;&nbsp;&nbsp; private int color;</PRE><PRE>&nbsp;&nbsp;&nbsp; public void setColor(int color) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.color = color;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public int getColor(){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return color;<BR>&nbsp;&nbsp;&nbsp; }<BR>}</PRE></DIV>
<P>　　这时一般我们会创建一个常量类，来存放颜色常量，如下：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>public interface Color {<BR>&nbsp;&nbsp;&nbsp; int RED = 0;<BR>&nbsp;&nbsp;&nbsp; int BLACK = 1;<BR>&nbsp;&nbsp;&nbsp; int YELLOW = 2;<BR>&nbsp;&nbsp;&nbsp; int BLUE = 3;<BR>&nbsp;&nbsp;&nbsp; int WHITE = 4;<BR>&nbsp;&nbsp;&nbsp; int ORANGE = 5;<BR>}</PRE></DIV>
<P>　　以后我们用的时候就可以这样：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>public class Client {<BR>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Flower f = new Flower();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f.setColor(Color.RED);<BR>&nbsp;&nbsp;&nbsp; }<BR>}</PRE></DIV>
<P>&nbsp; Color类就是一个我们自己来实现的枚举类，当然它并不是严格意义上的枚举类，而且JDK5.0之前还没有枚举。这时会出现一个问题：setColor参数是int型，那么也许用户会不小心用一个非法的int值赋进去，这样就可能产生BUG，如：f.setColor(100);显示100并非是我们设定中的颜色值。</P>
<P>　　在那本有名的java著作&lt;&lt;Effective java&gt;&gt; Joshua Bloch，用了专门的一章（第５章）来讨论这个问题，书中给出了一个比较严谨的解决方案，如下代码所示</P>
<P>（１）用Color类更改如下：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>public class Color {<BR>&nbsp;&nbsp;&nbsp; private final int color;</PRE><PRE>&nbsp;&nbsp;&nbsp; private Color(int color) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.color = color;<BR>&nbsp;&nbsp;&nbsp; }</PRE><PRE>&nbsp;&nbsp;&nbsp; public int getColorValue() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return color;<BR>&nbsp;&nbsp;&nbsp; }</PRE><PRE>&nbsp;&nbsp;&nbsp; public static final Color RED = new Color(0);<BR>&nbsp;&nbsp;&nbsp; public static final Color BLACK = new Color(1);<BR>&nbsp;&nbsp;&nbsp; public static final Color YELLOW = new Color(2);<BR>&nbsp;&nbsp;&nbsp; public static final Color BLUE = new Color(3);<BR>&nbsp;&nbsp;&nbsp; public static final Color WHITE = new Color(4);<BR>&nbsp;&nbsp;&nbsp; public static final Color ORANGE = new Color(5);<BR>}</PRE></DIV>
<P></P>
<P>（２）Flower类也要相应的更改，将int改为Color型。</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>public class Flower {<BR>&nbsp;&nbsp;&nbsp; private Color color;</PRE><PRE>&nbsp;&nbsp;&nbsp; public void setColor(Color color) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.color = color;<BR>&nbsp;&nbsp;&nbsp; }</PRE><PRE>&nbsp;&nbsp;&nbsp; public Color getColor() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return color;<BR>&nbsp;&nbsp;&nbsp; }<BR>}</PRE></DIV>
<P>（３）客户端Client不用修改。</P>
<P>　　这样Flower类的setColor方法就只接收Color，也不用担心用户不心传入非法的参数值了。</P>
<P></P>
<P><STRONG>三、新的特性：JDK5.0枚举</STRONG></P>
<P>（１）简单的例子</P>
<P>　　JDK5.0的枚举，正好可以解决上面我们讨论的问题，而且更简洁。还是用上面的代码做示例，只需要将Color类修改如下，Flower、Client都无法更改。</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>public enum Color {<BR>&nbsp;&nbsp;&nbsp; RED, BLACK, YELLOW, BLUE, WHITE, ORANGE<BR>}</PRE></DIV>
<P>　很简单吧。接下来我们做更深一步的说明：</P>
<UL>
<LI>所有枚举类都是java.lang.Enum的子类（JDK内核自动将Color隐性继承自Enum） 
<LI>RED...ORANGE都是Color的实例对象</LI></UL>
<P>　上面的Color枚举类，功能好象还和以前的例子不完全一样，我们再次修改如下。</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>public enum Color {<BR>&nbsp;&nbsp;&nbsp; RED(0), BLACK(1), YELLOW(2), BLUE(3), WHITE(4), ORANGE(5);<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; int color;<BR>&nbsp;&nbsp;&nbsp; Color(int color){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.color=color;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public int getColorValue(){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return color;<BR>&nbsp;&nbsp;&nbsp; }<BR>}<BR></PRE></DIV>
<P>　　从这里我们可以看到枚举类是如何创建构造函数及方法的，有一些隐性的东西要说明一下：</P>
<UL>
<LI>枚举类的构造函数要求是private的，如果象例子里那样不加修饰符，则Java会自动给加上。但如果你想加上public则会报错。 
<LI>RED(0), BLACK(1)...等枚举值必须定义在前面，而且最后一个枚举值ORANGE(5);未尾用分号结束。</LI></UL>
<P>（２）在循环中使用枚举类</P>
<P>　　枚举类都有一个values方法可以得到它值的数组：Color[] colors=Color.values();而且枚举类都支持泛型（以后的文章会重点说到），所以我们可以这样来遍历这个数组：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Color[] colors = Color.values();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (Color c : colors) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("color value=" + c.getColorValue());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</PRE></DIV>
<P>更简洁的写法是这样：</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (Color c : Color.values()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("color value=" + c.getColorValue());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</PRE></DIV>
<P>（３）在switch（分支）中使用枚举</P>
<P>　　如下代码示例，这里要注意将“case RED:”写成“case Color.RED:”是会报错的，因为JDK5.0可以自动根据“switch (color)”就判断入你要使用什么枚举类型了。从这里也可以看出JDK5.0确实为用户做了帖心的考虑，尽量让程序员少写代码，写更简单的代码。</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Color color = Color.RED;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (color) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case RED:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //process ... <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case BLACK:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //process ...<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case WHITE:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //process ...<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //process ...<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</PRE></DIV>
<P>（４）JDK5.0新增的集合：EnumMap 和EnumSet </P>
<P>　　给出两个例子，一切尽在不言中了。（说明：这两个例子用到了JDK5.0中泛型的知识）</P>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Map&lt;Color, String&gt; map = new EnumMap&lt;Color, String&gt;(Color.class);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.put(Color.RED, "红色");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.put(Color.BLACK, "黑色");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.put(Color.WHITE, "白色");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (Color c : Color.values()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(c + " chinese is: " + map.get(c));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</PRE></DIV><BR>
<DIV style="BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: 1px solid; WIDTH: 100%; PADDING-TOP: 1px; BORDER-BOTTOM: 1px solid; HEIGHT: 18px"><PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set all = EnumSet.allOf(Color.class);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EnumSet warmColors = EnumSet.of(Color.RED, Color.YELLOW);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set notWarmColors = EnumSet.complementOf(warmColors);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set notBlack = EnumSet.range(Color.RED, Color.YELLOW);<BR></PRE></DIV>
<P><STRONG></STRONG></P>
<P><STRONG>四、参考资料</STRONG></P>
<P><A href="http://dev.yesky.com/451/2044451_1.shtml">http://dev.yesky.com/451/2044451_1.shtml</A></P>
<H5><FONT size=3>五、作者简介</FONT></H5>
<P>陈刚，广西桂林人，著作有《Eclipse从入门到精通》<BR>您可以通过其博客了解更多信息和文章：<A href="http://www.ChenGang.com.cn"><FONT color=#000033>http://www.ChenGang.com.cn</FONT></A> </P>
<P></P>
<P></P>
<P></P>
<P><STRIKE></STRIKE></P>
<DIV class=clear></DIV></DIV><img src ="http://www.blogjava.net/chengang/aggbug/33189.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-03-02 13:53 <a href="http://www.blogjava.net/chengang/archive/2006/03/02/33189.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>