﻿<?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-MicroFish-随笔分类-Java</title><link>http://www.blogjava.net/liulu/category/14912.html</link><description>Open &amp; Open
&lt;a href="http://www.fastwebcounter.com" title="Free Web Counter"&gt;&lt;font color="red"&gt;&lt;script src="http://fastwebcounter.com/secure.php?s=www.blogjava.net/liulu"&gt;&lt;/script&gt;hits&lt;/font&gt;&lt;/a&gt;</description><language>zh-cn</language><lastBuildDate>Thu, 08 Mar 2007 06:58:36 GMT</lastBuildDate><pubDate>Thu, 08 Mar 2007 06:58:36 GMT</pubDate><ttl>60</ttl><item><title>抽象类和接口的区别</title><link>http://www.blogjava.net/liulu/archive/2007/03/08/102584.html</link><dc:creator>刘璐</dc:creator><author>刘璐</author><pubDate>Thu, 08 Mar 2007 05:27:00 GMT</pubDate><guid>http://www.blogjava.net/liulu/archive/2007/03/08/102584.html</guid><wfw:comment>http://www.blogjava.net/liulu/comments/102584.html</wfw:comment><comments>http://www.blogjava.net/liulu/archive/2007/03/08/102584.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liulu/comments/commentRss/102584.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liulu/services/trackbacks/102584.html</trackback:ping><description><![CDATA[
		<span style="FONT-WEIGHT: 400">
				<span class="unnamed4">
						<font style="FONT-SIZE: 9pt">abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制，正是由于这两种机制的存在，才赋予了Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性，甚至可以相互替换，因此很多开发者在进行抽象类定义时对于abstract class和interface的选择显得比较随意。其实，两者之间还是有很大的区别的，对于它们的选择甚至反映出对于问题领域本质的理解、对于设计意图的理解是否正确、合理。本文将对它们之间的区别进行一番剖析，试图给开发者提供一个在二者之间进行选择的依据。  <br /><br />理解抽象类  <br /><br />abstract class和interface在Java语言中都是用来进行抽象类（本文中的抽象类并非从abstract class翻译而来，它表示的是一个抽象体，而abstract class为Java语言中用于定义抽象类的一种方法，请读者注意区分）定义的，那么什么是抽象类，使用抽象类能为我们带来什么好处呢？  <br /><br />在面向对象的概念中，我们知道所有的对象都是通过类来描绘的，但是反过来却不是这样。并不是所有的类都是用来描绘对象的，如果一个类中没有包含足够的信息来描绘一个具体的对象，这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念，是对一系列看上去不同，但是本质上相同的具体概念的抽象。比如：如果我们进行一个图形编辑软件的开发，就会发现问题领域存在着圆、三角形这样一些具体概念，它们是不同的，但是它们又都属于形状这样一个概念，形状这个概念在问题领域是不存在的，它就是一个抽象概念。正是因为抽象的概念在问题领域没有对应的具体概念，所以用以表征抽象概念的抽象类是不能够实例化的。  <br /><br />在面向对象领域，抽象类主要用来进行类型隐藏。我们可以构造出一个固定的一组行为的抽象描述，但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类，而这一组任意个可能的具体实现则表现为所有可能的派生类。模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体，因此它可以是不允许修改的；同时，通过从这个抽象体派生，也可扩展此模块的行为功能。熟悉OCP的读者一定知道，为了能够实现面向对象设计的一个最核心的原则OCP(Open-Closed Principle)，抽象类是其中的关键所在。  <br /><br /><br />从语法定义层面看abstract class和interface  <br /><br />在语法层面，Java语言对于abstract class和interface给出了不同的定义方式，下面以定义一个名为Demo的抽象类为例来说明这种不同。  <br /><br />使用abstract class的方式定义Demo抽象类的方式如下：  <br /><br />abstract class Demo ｛  <br /> abstract void method1();  <br /> abstract void method2();  <br /> …  <br />｝  <br /><br />使用interface的方式定义Demo抽象类的方式如下：  <br /><br />interface Demo {  <br /> void method1();  <br /> void method2();  <br /> …  <br />}  <br /><br />在abstract class方式中，Demo可以有自己的数据成员，也可以有非abstarct的成员方法，而在interface方式的实现中，Demo只能够有静态的不能被修改的数据成员（也就是必须是static final的，不过在interface中一般不定义数据成员），所有的成员方法都是abstract的。从某种意义上说，interface是一种特殊形式的abstract class。  <br /><br />      从编程的角度来看，abstract class和interface都可以用来实现"design by contract"的思想。但是在具体的使用上面还是有一些区别的。  <br /><br />首先，abstract class在Java语言中表示的是一种继承关系，一个类只能使用一次继承关系。但是，一个类却可以实现多个interface。也许，这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。  <br /><br />其次，在abstract class的定义中，我们可以赋予方法的默认行为。但是在interface的定义中，方法却不能拥有默认行为，为了绕过这个限制，必须使用委托，但是这会 增加一些复杂性，有时会造成很大的麻烦。  <br /><br />在抽象类中不能定义默认行为还存在另一个比较严重的问题，那就是可能会造成维护上的麻烦。因为如果后来想修改类的界面（一般通过abstract class或者interface来表示）以适应新的情况（比如，添加新的方法或者给已用的方法中添加新的参数）时，就会非常的麻烦，可能要花费很多的时间（对于派生类很多的情况，尤为如此）。但是如果界面是通过abstract class来实现的，那么可能就只需要修改定义在abstract class中的默认行为就可以了。  <br /><br />同样，如果不能在抽象类中定义默认行为，就会导致同样的方法实现出现在该抽象类的每一个派生类中，违反了"one rule，one place"原则，造成代码重复，同样不利于以后的维护。因此，在abstract class和interface间进行选择时要非常的小心。  <br /><br /><br />从设计理念层面看abstract class和interface  <br /><br />上面主要从语法定义和编程的角度论述了abstract class和interface的区别，这些层面的区别是比较低层次的、非本质的。本小节将从另一个层面：abstract class和interface所反映出的设计理念，来分析一下二者的区别。作者认为，从这个层面进行分析才能理解二者概念的本质所在。  <br /><br />前面已经提到过，abstarct class在Java语言中体现了一种继承关系，要想使得继承关系合理，父类和派生类之间必须存在"is a"关系，即父类和派生类在概念本质上应该是相同的（参考文献〔3〕中有关于"is a"关系的大篇幅深入的论述，有兴趣的读者可以参考）。对于interface 来说则不然，并不要求interface的实现者和interface定义在概念本质上是一致的，仅仅是实现了interface定义的契约而已。为了使论述便于理解，下面将通过一个简单的实例进行说明。  <br /><br />考虑这样一个例子，假设在我们的问题领域中有一个关于Door的抽象概念，该Door具有执行两个动作open和close，此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型，定义方式分别如下所示：  <br /><br />使用abstract class方式定义Door：  <br /><br />abstract class Door {  <br /> abstract void open();  <br /> abstract void close()；  <br />}  <br /><br />   <br />使用interface方式定义Door：  <br /><br /><br />interface Door {  <br /> void open();  <br /> void close();  <br />}  <br /><br />   <br />其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。  <br /><br />如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢（在本例中，主要是为了展示abstract class和interface反映在设计理念上的区别，其他方面无关的问题都做了简化或者忽略）？下面将罗列出可能的解决方案，并从设计理念层面对这些不同的方案进行分析。  <br /><br />解决方案一：  <br /><br />简单的在Door的定义中增加一个alarm方法，如下：  <br /><br />abstract class Door {  <br /> abstract void open();  <br /> abstract void close()；  <br /> abstract void alarm();  <br />}  <br /><br />   <br />或者  <br /><br />interface Door {  <br /> void open();  <br /> void close();  <br /> void alarm();  <br />}  <br /><br />   <br />那么具有报警功能的AlarmDoor的定义方式如下：  <br /><br />class AlarmDoor extends Door {  <br /> void open() { … }  <br /> void close() { … }  <br /> void alarm() { … }  <br />}  <br /><br />   <br />或者  <br /><br />class AlarmDoor implements Door ｛  <br /> void open() { … }  <br /> void close() { … }  <br /> void alarm() { … }  <br />｝  <br /><br />这种方法违反了面向对象设计中的一个核心原则ISP（Interface Segregation Priciple），在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变（比如：修改alarm方法的参数）而改变，反之依然。  <br /><br />解决方案二：  <br /><br />既然open、close和alarm属于两个不同的概念，根据ISP原则应该把它们分别定义在代表这两个概念的抽象类中。定义方式有：这两个概念都使用abstract class方式定义；两个概念都使用interface方式定义；一个概念使用abstract class方式定义，另一个概念使用interface方式定义。  <br /><br />显然，由于Java语言不支持多重继承，所以两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的，但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。我们一一来分析、说明。  <br /><br />如果两个概念都使用interface方式来定义，那么就反映出两个问题：1、我们可能没有理解清楚问题领域，AlarmDoor在概念本质上到底是Door还是报警器？2、如果我们对于问题领域的理解没有问题，比如：我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的，那么我们在实现时就没有能够正确的揭示我们的设计意图，因为在这两个概念的定义上（均使用interface方式定义）反映不出上述含义。  <br /><br />如果我们对于问题领域的理解是：AlarmDoor在概念本质上是Door，同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢？前面已经说过，abstract class在Java语言中表示一种继承关系，而继承关系在本质上是"is a"关系。所以对于Door这个概念，我们应该使用abstarct class方式来定义。另外，AlarmDoor又具有报警功能，说明它又能够完成报警概念中定义的行为，所以报警概念可以通过interface方式定义。如下所示：  <br /><br />abstract class Door {  <br /> abstract void open();  <br /> abstract void close()；  <br />}  <br />interface Alarm {  <br /> void alarm();  <br />}  <br />class AlarmDoor extends Door implements Alarm {  <br /> void open() { … }  <br /> void close() { … }  <br />    void alarm() { … }  <br />}  <br /><br />   <br />这种实现方式基本上能够明确的反映出我们对于问题领域的理解，正确的揭示我们的设计意图。其实abstract class表示的是"is a"关系，interface表示的是"like a"关系，大家在选择时可以作为一个依据，当然这是建立在对问题领域的理解上的，比如：如果我们认为AlarmDoor在概念本质上是报警器，同时又具有Door的功能，那么上述的定义方式就要反过来了。</font>
				</span>
		</span>
<img src ="http://www.blogjava.net/liulu/aggbug/102584.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liulu/" target="_blank">刘璐</a> 2007-03-08 13:27 <a href="http://www.blogjava.net/liulu/archive/2007/03/08/102584.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转 J2EE开发之常用开源项目介绍</title><link>http://www.blogjava.net/liulu/archive/2006/12/28/90547.html</link><dc:creator>刘璐</dc:creator><author>刘璐</author><pubDate>Thu, 28 Dec 2006 09:36:00 GMT</pubDate><guid>http://www.blogjava.net/liulu/archive/2006/12/28/90547.html</guid><wfw:comment>http://www.blogjava.net/liulu/comments/90547.html</wfw:comment><comments>http://www.blogjava.net/liulu/archive/2006/12/28/90547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liulu/comments/commentRss/90547.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liulu/services/trackbacks/90547.html</trackback:ping><description><![CDATA[
		<div twffan="done">主要就我所了解的J2EE开发的框架或开源项目做个介绍,可以根据需求选用适当的开源组件进行开发.主要还是以Spring为核心,也总结了一些以前web开发常用的开源工具和开源类库</div>
		<div twffan="done"> </div>
		<div twffan="done">1持久层:</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">1)Hibernate</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">这个不用介绍了,用的很频繁,用的比较多的是映射,包括继承映射和父子表映射</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">对于DAO在这里介绍个在它基础上开发的包bba96,目前最新版本是bba96 2.0它对Hibernate进行了封装, 查询功能包括执行hsql或者sql查询/更新的方法，如果你要多层次逻辑的条件查询可以自己组装QueryObject.可以参考它做HibernateDAO.也可以直接利用它</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">2) iBATIS</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">另一个ORM工具,Apache的,没有Hibernate那么集成,自由度比较大</div>
		<div twffan="done">2:SpringMVC</div>
		<div twffan="done">
				<span twffan="done">       </span>原理说明和快速入门:</div>
		<div twffan="done">
				<span twffan="done">       </span>配置文件为:</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Spring的配置文件默认为WEB-INF/xxxx-servelet.xm其中xxx为web.xml中org.springframework.web.servlet.DispatcherServlet的servlet-name。</div>
		<div twffan="done">
				<span twffan="done">       Action</span>分发:</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Spring将按照配置文件定义的URL，Mapping到具体Controller类，再根据URL里的action= xxx或其他参数，利用反射调用Controller里对应的Action方法。</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">输入数据绑定:</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Spring提供Binder 通过名字的一一对应反射绑定Pojo，也可以直接从request.getParameter()取数据。</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">输入数据验证</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Sping 提供了Validator接口当然还可以使用开源的Commons-Validaor支持最好</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Interceptor(拦截器)</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Spring的拦截器提供接口需要自己编写,在这点不如WebWork做的好.全面 </div>
		<div twffan="done">
				<span twffan="done">       (</span>这里提一下WebWork和Struts的区别最主要的区别在于WebWork在建立一个Action时是新New一个对象而Struts是SingleMoule所有的都继承它的一个Action,所以根据项目需要合适的选择.)</div>
		<div twffan="done">3:View层</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">1) 标签库:JSP2.0/JSTL</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">由于Webwork或Spring的标签确实很有限,一般view层用JSTL标签,而且据说JSTL设计很好速度是所有标签中最快的使用起来也很简单</div>
		<div style="TEXT-INDENT: 21pt" twffan="done"> </div>
		<div style="TEXT-INDENT: 21pt" twffan="done">2) 富客户端:DOJO Widgets, YUI(YahooUI),FCKEditor, Coolest日历控件</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Dojo主要提供Tree, Tab等富客户端控件,可以用其进行辅助客户端开发</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">YahooUI和DOJO一样它有自己的一套javascript调试控制台,主要支持ajax开发也有很多Tree,Table,Menu等富客户端控件</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">FCKEditor 最流行的文本编辑器</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Coolest日历控件 目前很多日历控件可用,集成在项目中也比较简单,这个只是其中的一个,界面不错的说..</div>
		<div style="TEXT-INDENT: 21pt" twffan="done"> </div>
		<div style="TEXT-INDENT: 21pt" twffan="done">3) JavaScript:Prototype.js</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Prototype.js作为javascript的成功的开源框架，封装了很多好用的功能,通过它很容易编写AJAX应用,现在AJAX技术逐渐成熟,框架资源比较丰富,比如YUI,DWR等等,也是因为JavaScript没有合适的调试工具,所以没有必要从零开始编写AJAX应用,个人认为多用一些成熟的Ajax框架实现无刷新更新页面是不错的选择.</div>
		<div style="TEXT-INDENT: 21pt" twffan="done"> </div>
		<div style="TEXT-INDENT: 21pt" twffan="done">4)表格控件:Display Tag ,Extreme Table</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">这两个的功能差不多,都是View层表格的生成,界面也比较相向,可以导出Excel,Pdf,对Spring支持很容易.</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">相比较而言比较推荐ExtremeTable,它的设计很好功能上比DisplayTag多一些,支持Ajax,封装了一些拦截器,而且最方面的是在主页wiki中有详细的中文使用文档.</div>
		<div style="TEXT-INDENT: 21pt" twffan="done"> </div>
		<div style="TEXT-INDENT: 21pt" twffan="done">5):OSCache</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">OSCache是OpenSymphony组织提供的一个J2EE架构中Web应用层的缓存技术实现组件,Cache是一种用于提高系统响应速度、改善系统运行性能的技术。尤其是在Web应用中，通过缓存页面的输出结果，可以很显著的改善系统的稳定性和运行性能。</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">它主要用在处理短时间或一定时间内一些数据或页面不会发生变化,或将一些不变的统计报表,缓冲在内存,可以充分的减轻服务器的压力,防治负载平衡,快速重启服务器(通过硬盘缓存).</div>
		<div style="TEXT-INDENT: 21pt" twffan="done"> </div>
		<div style="TEXT-INDENT: 21pt" twffan="done">6)SiteMesh</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">sitemesh应用Decorator模式主要用于提高页面的可维护性和复用性，其原理是用Filter截取request和response,把页面组件head,content,banner结合为一个完整的视图。通常我们都是用include标签在每个jsp页面中来不断的包含各种header, stylesheet, scripts and footer，现在，在sitemesh的帮助下，我们删掉他们轻松达到复合视图模式.</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Sitemesh也是<span twffan="done"> OpenSymphony</span>的一个项目现在最近的版本是2.2,目前OpenSymphony自从04年就没有更新的版本了..感觉它还是比较有创新的一种页面组装方式, OpenSymphony开源组织的代码一般写的比较漂亮,可以改其源代码对自己的项目进行适配.</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">测试发现Sitemesh还存在一些问题,比如中文问题,它的默认编码是iso-8859-1在使用时候需要做一些改动.</div>
		<div style="TEXT-INDENT: 21pt" twffan="done"> </div>
		<div style="TEXT-INDENT: 21pt" twffan="done">7)CSS,XHTML</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">这个不用说了,遵循W3C标准的web页面开发.</div>
		<div style="TEXT-INDENT: 21pt" twffan="done"> </div>
		<div style="TEXT-INDENT: 21pt" twffan="done">8)分页标签: pager-taglib组件</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Pager-taglib 是一套分页标签库，可以灵活地实现多种不同风格的分页导航页面，并且可以很好的与服务器分页逻辑分离.使用起来也比较简单.</div>
		<div style="TEXT-INDENT: 21pt" twffan="done"> </div>
		<div style="TEXT-INDENT: 21pt" twffan="done">9)Form: Jodd Form taglib</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Jodd Form taglib使用比较简单,只要把&lt;form&gt;的头尾以&lt;jodd:form bean= "mybean"&gt;包住</div>
		<div twffan="done">就会自动绑定mybean, 自动绑定mybean的所有同名属性到普通html标记input, selectbox, checkbox,radiobox.....在这些input框里不用再写任何代码…</div>
		<div twffan="done">
				<span twffan="done">       </span>
		</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">10)Ajax:DWR</div>
		<div twffan="done">
				<span twffan="done">       J2EE</span>应用最常用的ajax框架</div>
		<div twffan="done">
				<span twffan="done">       </span>
		</div>
		<div twffan="done">
				<span twffan="done">       11)</span>报表 图表</div>
		<div style="MARGIN-LEFT: 21pt" twffan="done">Eclipse BIRT功能比较强大,也很庞大..好几十<span twffan="done">M,一般没有特别需求或别的图表设计软件可以解决的不用它</span></div>
		<div style="TEXT-INDENT: 21pt" twffan="done">JasperReports+ iReport是一个基于Java的开源报表工具，它可以在Java环境下像其它IDE报表工具一样来制作报表。JasperReports支持PDF、HTML、XLS、CSV和XML文件输出格式。JasperReports是当前Java开发者最常用的报表工具。</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">JFreeChart主要是用来制作各种各样的图表，这些图表包括：饼图、柱状图(普通柱状图以及堆栈柱状图)、线图、区域图、分布图、混合图、甘特图以及一些仪表盘等等。</div>
		<div twffan="done">
				<span twffan="done">      琴棋报表,国产的..重点推荐,适合中国的情况,开放源代码，使用完全免费。纯JAVA开发，适用多种系统平台。特别适合B/S结构的系统。官方网站有其优点介绍,看来用它还是不错的选择,最重要的是支持国产呵呵</span>
		</div>
		<div twffan="done"> </div>
		<div twffan="done">4:权限控制: Acegi</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Acegi是Spring Framework 下最成熟的安全系统，它提供了强大灵活的企业级安全服务，如完善的认证和授权机制，Http资源访问控制，Method 调用访问控制等等,支持CAS</div>
		<div twffan="done">(耶鲁大学的单点登陆技术,这个单点登陆方案比较出名.我也进行过配置使用,可以根据项目需要,如果用户分布在不同的地方不同的系统通用一套登陆口令可以用它进行解决,一般注册机登陆机就是这样解决的)</div>
		<div twffan="done">
				<span twffan="done">       Acegi</span>只是于Spring结合最好的安全框架,功能比较强大,当然还有一些其他的安全框架,这里列举一些比较流行的是我从网上找到的,使用方法看其官方文档把…</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">JAAS, Seraph, jSai - Servlet Security, Gabriel, JOSSO, Kasai, jPAM, OpenSAML都是些安全控制的框架..真够多的呵呵</div>
		<div twffan="done"> </div>
		<div twffan="done">5:全文检索</div>
		<div twffan="done">
				<span twffan="done">       1) Lucene</span>
		</div>
		<div twffan="done">
				<span twffan="done">       Lucene</span>是一套全文索引接口,可以通过它将数据进行倒排文件处理加入索引文件,它的索引速度和查询速度是相当快的,查询百万级数据毫秒级出结果,现在最火的Apache开源项目,版本更新速度很快现在已经到了2.0,每个版本更新的都比较大,目前用的最多的版本应该是1.4.3,但它有个不太方面的地方单个索引文件有2G文件限制,现在2.0版本没有这个限制,我研究的比较多,它的扩展性比较好,可以很方面的扩充其分词接口和查询接口.</div>
		<div twffan="done">
				<span twffan="done">       </span>基于它的开发的系统很多,比如最常用的Eclipse的搜索功能,还有一些开源的软件比如Compass,Nutch,Lius,还有我最近做的InSearch(企业级FTP文件网页搜索)</div>
		<div twffan="done">6:公共Util类</div>
		<div twffan="done">
				<span twffan="done">       </span>主要是Jakarta-Commons类库,其中最常用得是以下几个类库</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">1) Jakarta-Commons-Language</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">
				<span twffan="done">       </span>最常用得类是StringUtils类,提供了使用的字符串处理的常用方法效率比较高</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">2) Jakarta-Commons-Beantuils</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">
				<span twffan="done">       </span>主要用Beantuils能够获得反射函数封装及对嵌套属性，map,array型属性的读取。</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">3) Jakarta-Commons-Collections</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">
				<span twffan="done">       </span>里面有很多Utils方法</div>
		<div style="TEXT-INDENT: 21pt" twffan="done"> </div>
		<div twffan="done">7 日志管理</div>
		<div twffan="done">
				<span twffan="done">       Log4J</span>
		</div>
		<div twffan="done">
				<span twffan="done">       </span>任务是日志记录,分为Info,Warn,error几个层次可以更好的调试程序</div>
		<div twffan="done"> </div>
		<div twffan="done">8 开源的J2EE框架</div>
		<div twffan="done">
				<span twffan="done">       1) Appfuse</span>
		</div>
		<div twffan="done">
				<span twffan="done">              Appfuse</span>是Matt Raible 开发的一个指导性的入门级J2EE框架, 它对如何集成流行的Spring、Hibernate、iBatis、Struts、Xdcolet、JUnit等基础框架给出了示范. 在持久层，AppFuse采用了Hibernate O/R映射工具；在容器方面，它采用了Spring,用户可以自由选择Struts、Spring/MVC，Webwork，JSF这几个Web框架。</div>
		<div twffan="done">
				<span twffan="done">       </span>
		</div>
		<div twffan="done">
				<span twffan="done">       2) SpringSide</span>
		</div>
		<div twffan="done">
				<span twffan="done">       .SpringSide</span>较完整的演示了企业应用的各个方面,是一个电子商务网站的应用 SpringSide也大量参考了Appfuse中的优秀经验。最重要的是它是国内的一个开源项目,可以了解到国内现在的一些实际技术动态和方向很有指导意义…</div>
		<div twffan="done"> </div>
		<div twffan="done">9:模版 Template </div>
		<div style="TEXT-INDENT: 21pt" twffan="done">主要有Veloctiy和Freemarker</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">模板用Servlet提供的数据动态地生成 HTML。编译器速度快，输出接近静态HTML<span twffan="done">             </span>页面的速度。</div>
		<div style="TEXT-INDENT: 21pt" twffan="done"> </div>
		<div twffan="done">10:工作流</div>
		<div twffan="done">
				<span twffan="done">       </span>我所知道比较出名的主要有JBpm Shark Osworkflow,由于对它没有过多的研究所以还不是很清楚之间有什么区别.</div>
		<div twffan="done"> </div>
		<div twffan="done">项目管理软件</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">dotProject:是一个基于LAMP的开源项目管理软件。最出名的项目管理软件</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">JIRA: 项目计划，任务安排，错误管理</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">Bugzilla:提交和管理bug,和eclipse集成,可以通过安装MyEclipse配置一下即可使用</div>
		<div style="MARGIN-LEFT: 52.5pt; TEXT-INDENT: -31.5pt" twffan="done">BugFree借鉴微软公司软件研发理念、免费开放源代码、基于Web的精简版Bug管理</div>
		<div style="TEXT-INDENT: 21pt" twffan="done">CVS:这个就不介绍了都在用.</div>
		<div style="MARGIN-LEFT: 47.25pt; TEXT-INDENT: -26.25pt" twffan="done">SVN: SubVersion已逐渐超越CVS，更适应于JavaEE的项目。Apache用了它很久后，Sourceforge刚刚推出SVN的支持。</div>
		<div style="MARGIN-LEFT: 47.25pt; TEXT-INDENT: -26.25pt" twffan="done">测试用例:主要JUnit单元测试,编写TestCase,Spring也对Junit做了很好的支持</div>
		<div twffan="done"> </div>
		<div twffan="done">后记:</div>
		<div twffan="done">
				<span twffan="done">       </span>以Spring为主的应用开发可选用的组件中间件真是眼花缭乱,所以针对不同的项目需求可以利用不同的开源产品解决,比如用Spring+Hibernate/ iBATIS或Spring+WebWork+Hibernate/ iBATIS或Spring+Struts+Hibernate/ iBATIS,合理的框架设计和代码复用设计对项目开发效率和程序性能有很大的提高,也有利于后期的维护.</div>
<img src ="http://www.blogjava.net/liulu/aggbug/90547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liulu/" target="_blank">刘璐</a> 2006-12-28 17:36 <a href="http://www.blogjava.net/liulu/archive/2006/12/28/90547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA断言使用</title><link>http://www.blogjava.net/liulu/archive/2006/10/24/77005.html</link><dc:creator>刘璐</dc:creator><author>刘璐</author><pubDate>Tue, 24 Oct 2006 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/liulu/archive/2006/10/24/77005.html</guid><wfw:comment>http://www.blogjava.net/liulu/comments/77005.html</wfw:comment><comments>http://www.blogjava.net/liulu/archive/2006/10/24/77005.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liulu/comments/commentRss/77005.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liulu/services/trackbacks/77005.html</trackback:ping><description><![CDATA[相信学过c,c++的朋友一定不会对断言感到陌生。下面介绍一下断言在JAVA中的使用，JAVA是从JDK1.4才开始支持断言的（添加了关键字assert）,请注意老版的JRE不支持。<br /><br /><h3>断言概述</h3><br />  编写代码时，我们总是会做出一些假设，断言就是用于在代码中<b>捕捉这些假设</b><br />  可以将断言看作是<b>异常处理的一种高级形式</b><br />  断言表示为一些布尔表达式，程序员相信在程序中的某个特定点该表达式值为真<br />  可以在任何时候启用和禁用断言验证，因此可以在测试时启用断言而在部署时禁用断言。同样，程序投入运行后，最终用户在遇到问题时可以重新起用断言。<br />  使用断言可以创建更稳定，品质更好且易于除错的代码<br />  当需要在一个值为FALSE时中断当前操作的话，可以使用断言<br />  单元测试必须使用断言（Junit/JunitX）<br />  除了类型检查和单元测试外，断言还提供了一种确定个种特性是否在程序中得到维护的极好的方法<br />  使用断言使我们向<b>按契约式设计</b>更近了一部<br /><br /><h3>常见的断言特性</h3><br />  前置条件断言：代码执行之前必须具备的特性<br />  后置条件断言：代码执行之后必须具备的特性<br />  前后不变断言：代码执行前后不能变化的特性<br /><br /><h3>断言使用方式</h3><br />  断言可以有两种形式<br />  1.assert Expression1<br />  2.assert Expression1:Expression2<br />  其中Expression1应该总是一个布尔值，Expression2是断言失败时输出的失败消息的字符串。如果Expression1为假，则抛出一个 AssertionError，这是一个错误，而不是一个异常，也就是说是一个不可控制异常（unchecked Exception),AssertionError由于是错误，所以可以不捕获，但不推荐这样做，因为那样会使你的系统进入不稳定状态。<br /><br /><h3>起用断言</h3><br />  断言在默认情况下是关闭的，要在编译时启用断言，需要使用source1.4标记 既javac source1.4 Test.java ,在运行时启用断言需要使用 -ea参数 。要在系统类中启用和禁用断言可以使用 -esa 和 -dsa参数。<br />  <br />例如：<br />public class AssertExampleOne{<br />   public AssertExampleOne(){}<br />   public static void main(String args[]){<br />      int x=10;<br />      System.out.println("Testing Assertion that x==100");<br />      assert x==100:"Out assertion failed!";<br />      System.out.println("Test passed!");<br />   }<br />}<br /><br />如果编译时未加 -source1.4,则编译通不过<br />在执行时未加 -ea 时输出为<br />Testing Assertion that x==100<br />Test passed<br />jre忽略了断言的就代码，而使用了该参数就会输出为<br />Testing Assertion that x==100<br />Exception in thread "main" java.lang.AssertionError: Out assertion failed!<br />        at AssertExampleOne.main(AssertExampleOne.java:6)<br /><br /><h3>断言的副作用</h3><br />  由于程序员的问题，断言的使用可能会带来副作用 ，例如：<br />  boolean isEnable=false;<br />  //...<br />  assert isEnable=true;<br />  这个断言的副作用是因为它修改了程序中变量的值并且未抛出错误，这样的错误如果不细心的检查是很难发现的。但是同时我们可以根据以上的副作用得到一个有用的特性，根据它来测试断言是否打开。<br /><br /> public class AssertExampleTwo{<br /><br />   public static void main(String args[]){<br />     boolean isEnable=false;<br />     //...<br />     assert isEnable=true;<br />     if(isEnable==false){<br />       throw new RuntimeException("Assertion shoule be enable!");<br />     }<br />   }<br />}<br /><br /><h3>何时需要使用断言</h3><br />  1.可以在预计正常情况下程序不会到达的地方放置断言 ：assert false<br />  2.断言可以用于检查传递给私有方法的参数。（对于公有方法，因为是提供给外部的接口，所以必须在方法中有相应的参数检验才能保证代码的健壮性）<br />  3.使用断言测试方法执行的前置条件和后置条件<br />  4.使用断言检查类的不变状态，确保任何情况下，某个变量的状态必须满足。（如age属性应大于0小于某个合适值）<br /><br /><h3>什么地方不要使用断言</h3><br />  断言语句不是永远会执行，可以屏蔽也可以启用<br />因此：<br />  1.不要使用断言作为公共方法的参数检查，公共方法的参数永远都要执行<br />  2.断言语句不可以有任何边界效应，不要使用断言语句去修改变量和改变方法的返回值<br /><br />参考：<br />http://jcp.org/en/jsr/detail?id=41<br />http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html<br />http://www-128.ibm.com/developworkers/cn/java/jdiag0723/<br /><a href="http://www-128.ibm.com/developworkers/cn/java/jmerlin/part9/"><font color="#0e4d8b">http://www-128.ibm.com/developworkers/cn/java/jmerlin/part9/</font></a><img src ="http://www.blogjava.net/liulu/aggbug/77005.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liulu/" target="_blank">刘璐</a> 2006-10-24 16:17 <a href="http://www.blogjava.net/liulu/archive/2006/10/24/77005.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>static方法不应该被重写</title><link>http://www.blogjava.net/liulu/archive/2006/10/24/76933.html</link><dc:creator>刘璐</dc:creator><author>刘璐</author><pubDate>Tue, 24 Oct 2006 03:47:00 GMT</pubDate><guid>http://www.blogjava.net/liulu/archive/2006/10/24/76933.html</guid><wfw:comment>http://www.blogjava.net/liulu/comments/76933.html</wfw:comment><comments>http://www.blogjava.net/liulu/archive/2006/10/24/76933.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liulu/comments/commentRss/76933.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liulu/services/trackbacks/76933.html</trackback:ping><description><![CDATA[
		<p>如果你认为重写只是在子类中简单的替换了一个方法，你就很容易认为static 方法也能<br />被重写。事实上，我有很多包含人们举例指明static 方法能被重写的代码的邮件。然而，这<br />些并没有考虑方法重写在运行时决定哪个版本的方法被调用的细节问题。下面的代码似乎表<br />明static 方法是怎样被重写的。<br />class Base{<br />   static void amethod(){<br />   System.out.println("Base.amethod");<br />   }<br />}<br />public class Cravengib extends Base{<br />   public static void main(String arg[]){<br />      Cravengib cg = new Cravengib();<br />      cg.amethod();<br />   }<br />   static void amethod(){<br />      System.out.println("Cravengib.amethod");<br />   }<br />}<br />如果你编译并运行这段代码，你会发现输出文本Cravengib.amethod，这似乎很好的指<br />明了重写。然而，对于重写，还有相对于在子类中使用一个方法简单替换另一个方法更多的<br />东西。还有运行时决定的方法基于引用的类的类型的问题，这可以通过制造正在被实例化的<br />类的引用类型（实例初始化语句的左半部分）来说明。<br />在上面的例子中，因为名字叫amethod 的方法与类发生了关联，而不是与特定的类的实<br />例相关联，它不在乎什么类型的类正在创建它，而仅仅在意引用的类型。因此，如果你在调<br />用amethod 前改变一下这一行，<br />Base cg= new Cravengib()<br />你就会发现当你运行程序时，你会得到输出：Base.amethod<br />cg 是一个类Cravengib 在内存中的一个Base 类型的实例的引用（或者指针）。如果一个static<br />方法被调用了，JVM 不会检查什么类型正在指向它，它只会调用跟Base 类相关联的方法的<br />实例。<br />与上面的情况相对比：当一个方法被重写时，JVM 检查通过引用正在指向的类的类型，<br />并调用此类型相关的方法。可以结束这个例子了，如果你将两个版本的amethod 方法改变为<br />非static，并依然创建类：<br />Base cg= new Cravengib()<br />编译并运行上述代码，你会发现amethod 已经被重写了，并且输出Cravengib.amethod。</p>
<img src ="http://www.blogjava.net/liulu/aggbug/76933.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liulu/" target="_blank">刘璐</a> 2006-10-24 11:47 <a href="http://www.blogjava.net/liulu/archive/2006/10/24/76933.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java反射机制</title><link>http://www.blogjava.net/liulu/archive/2006/09/08/68567.html</link><dc:creator>刘璐</dc:creator><author>刘璐</author><pubDate>Fri, 08 Sep 2006 09:56:00 GMT</pubDate><guid>http://www.blogjava.net/liulu/archive/2006/09/08/68567.html</guid><wfw:comment>http://www.blogjava.net/liulu/comments/68567.html</wfw:comment><comments>http://www.blogjava.net/liulu/archive/2006/09/08/68567.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liulu/comments/commentRss/68567.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liulu/services/trackbacks/68567.html</trackback:ping><description><![CDATA[Reflection 是 Java 程序开发语言的特征之一，它允许运行中的 Java 程序对自身进行检查，或者说“自审”，并能直接操作程序的内部属性。例如，使用它能获得 Java 类中各成员的名称并显示出来。<br /><br />Java 的这一能力在实际应用中也许用得不是很多，但是在其它的程序设计语言中根本就不存在这一特性。例如，Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。<br /><br />JavaBean 是 reflection 的实际应用之一，它能让一些工具可视化的操作软件组件。这些工具通过 reflection 动态的载入并取得 Java 组件(类) 的属性。<br /><br /><br /><br />1. 一个简单的例子<br /><br />考虑下面这个简单的例子，让我们看看 reflection 是如何工作的。<br /><br />import java.lang.reflect.*;<br />public class DumpMethods {<br />   public static void main(String args[]) {<br />       try {<br />           Class c = Class.forName(args[0]);<br />           Method m[] = c.getDeclaredMethods();<br />           for (int i = 0; i &lt; m.length; i++)<br />               System.out.println(m[i].toString());<br />       } catch (Throwable e) {<br />           System.err.println(e);<br />       }<br />   }<br />}<br /><br />按如下语句执行：<br /><br />java DumpMethods java.util.Stack<br /><br />它的结果输出为：<br /><br />public java.lang.Object java.util.Stack.push(java.lang.Object)<br /><br />public synchronized java.lang.Object java.util.Stack.pop()<br /><br />public synchronized java.lang.Object java.util.Stack.peek()<br /><br />public boolean java.util.Stack.empty()<br /><br />public synchronized int java.util.Stack.search(java.lang.Object)<br /><br />这样就列出了java.util.Stack 类的各方法名以及它们的限制符和返回类型。<br /><br />这个程序使用 Class.forName 载入指定的类，然后调用 getDeclaredMethods 来获取这个类中定义了的方法列表。java.lang.reflect.Methods 是用来描述某个类中单个方法的一个类。<br /><br />2.开始使用 Reflection<br /><br />用于 reflection 的类，如 Method，可以在 java.lang.relfect 包中找到。使用这些类的时候必须要遵循三个步骤：第一步是获得你想操作的类的 java.lang.Class 对象。在运行中的 Java 程序中，用 java.lang.Class 类来描述类和接口等。<br /><br />下面就是获得一个 Class 对象的方法之一：<br /><br />Class c = Class.forName("java.lang.String");<br /><br />这条语句得到一个 String 类的类对象。还有另一种方法，如下面的语句：<br /><br />Class c = int.class;<br /><br />或者<br /><br />Class c = Integer.TYPE;<br /><br />它们可获得基本类型的类信息。其中后一种方法中访问的是基本类型的封装类 (如 Integer) 中预先定义好的 TYPE 字段。<br /><br />第二步是调用诸如 getDeclaredMethods 的方法，以取得该类中定义的所有方法的列表。<br /><br />一旦取得这个信息，就可以进行第三步了——使用 reflection API 来操作这些信息，如下面这段代码：<br /><br />Class c = Class.forName("java.lang.String");<br /><br />Method m[] = c.getDeclaredMethods();<br /><br />System.out.println(m[0].toString());<br /><br />它将以文本方式打印出 String 中定义的第一个方法的原型。<br /><br />在下面的例子中，这三个步骤将为使用 reflection 处理特殊应用程序提供例证。<br /><br />模拟 instanceof 操作符<br /><br />得到类信息之后，通常下一个步骤就是解决关于 Class 对象的一些基本的问题。例如，Class.isInstance 方法可以用于模拟 instanceof 操作符：<br /><br />class A {<br />}<br /><br />public class instance1 {<br />   public static void main(String args[]) {<br />       try {<br />           Class cls = Class.forName("A");<br />           boolean b1 = cls.isInstance(new Integer(37));<br />           System.out.println(b1);<br />           boolean b2 = cls.isInstance(new A());<br />           System.out.println(b2);<br />       } catch (Throwable e) {<br />           System.err.println(e);<br />       }<br />   }<br />}<br /><br />在这个例子中创建了一个 A 类的 Class 对象，然后检查一些对象是否是 A 的实例。Integer(37) 不是，但 new A() 是。<br /><br />3.找出类的方法<br /><br />找出一个类中定义了些什么方法，这是一个非常有价值也非常基础的 reflection 用法。下面的代码就实现了这一用法：<br /><br />import java.lang.reflect.*;<br /><br />public class method1 {<br />   private int f1(Object p, int x) throws NullPointerException {<br />       if (p == null)<br />           throw new NullPointerException();<br />       return x;<br />   }<br /><br />   public static void main(String args[]) {<br />       try {<br />           Class cls = Class.forName("method1");<br />           Method methlist[] = cls.getDeclaredMethods();<br />           for (int i = 0; i &lt; methlist.length; i++) {<br />               Method m = methlist[i];<br />               System.out.println("name = " + m.getName());<br />               System.out.println("decl class = " + m.getDeclaringClass());<br />               Class pvec[] = m.getParameterTypes();<br />               for (int j = 0; j &lt; pvec.length; j++)<br />                   System.out.println("param #" + j + " " + pvec[j]);<br />               Class evec[] = m.getExceptionTypes();<br />               for (int j = 0; j &lt; evec.length; j++)<br />                   System.out.println("exc #" + j + " " + evec[j]);<br />               System.out.println("return type = " + m.getReturnType());<br />               System.out.println("-----");<br />           }<br />       } catch (Throwable e) {<br />           System.err.println(e);<br />       }<br />   }<br />}<br /><br />这个程序首先取得 method1 类的描述，然后调用 getDeclaredMethods 来获取一系列的 Method 对象，它们分别描述了定义在类中的每一个方法，包括 public 方法、protected 方法、package 方法和 private 方法等。如果你在程序中使用 getMethods 来代替 getDeclaredMethods，你还能获得继承来的各个方法的信息。<br /><br />取得了 Method 对象列表之后，要显示这些方法的参数类型、异常类型和返回值类型等就不难了。这些类型是基本类型还是类类型，都可以由描述类的对象按顺序给出。<br /><br />输出的结果如下：<br /><br />name = f1<br /><br />decl class = class method1<br /><br />param #0 class java.lang.Object<br /><br />param #1 int<br /><br />exc #0 class java.lang.NullPointerException<br /><br />return type = int<br /><br />-----<br /><br />name = main<br /><br />decl class = class method1<br /><br />param #0 class [Ljava.lang.String;<br /><br />return type = void<br /><br />-----<br /><br /><br />4.获取构造器信息<br /><br />获取类构造器的用法与上述获取方法的用法类似，如：<br /><br />import java.lang.reflect.*;<br /><br />public class constructor1 {<br />   public constructor1() {<br />   }<br /><br />   protected constructor1(int i, double d) {<br />   }<br /><br />   public static void main(String args[]) {<br />       try {<br />           Class cls = Class.forName("constructor1");<br />           Constructor ctorlist[] = cls.getDeclaredConstructors();<br />           for (int i = 0; i &lt; ctorlist.length; i++) {<br />               Constructor ct = ctorlist[i];<br />               System.out.println("name = " + ct.getName());<br />               System.out.println("decl class = " + ct.getDeclaringClass());<br />               Class pvec[] = ct.getParameterTypes();<br />               for (int j = 0; j &lt; pvec.length; j++)<br />                   System.out.println("param #" + j + " " + pvec[j]);<br />               Class evec[] = ct.getExceptionTypes();<br />               for (int j = 0; j &lt; evec.length; j++)<br />                   System.out.println("exc #" + j + " " + evec[j]);<br />               System.out.println("-----");<br />           }<br />       } catch (Throwable e) {<br />           System.err.println(e);<br />       }<br />   }<br />}<br /><br />这个例子中没能获得返回类型的相关信息，那是因为构造器没有返回类型。<br /><br />这个程序运行的结果是：<br /><br />name = constructor1<br /><br />decl class = class constructor1<br /><br />-----<br /><br />name = constructor1<br /><br />decl class = class constructor1<br /><br />param #0 int<br /><br />param #1 double<br /><br />-----<br /><br />5.获取类的字段(域)<br /><br />找出一个类中定义了哪些数据字段也是可能的，下面的代码就在干这个事情：<br /><br /><br />import java.lang.reflect.*;<br /><br />public class field1 {<br />   private double d;<br />   public static final int i = 37;<br />   String s = "testing";<br /><br />   public static void main(String args[]) {<br />       try {<br />           Class cls = Class.forName("field1");<br />           Field fieldlist[] = cls.getDeclaredFields();<br />           for (int i = 0; i &lt; fieldlist.length; i++) {<br />               Field fld = fieldlist[i];<br />               System.out.println("name = " + fld.getName());<br />               System.out.println("decl class = " + fld.getDeclaringClass());<br />               System.out.println("type = " + fld.getType());<br />               int mod = fld.getModifiers();<br />               System.out.println("modifiers = " + Modifier.toString(mod));<br />               System.out.println("-----");<br />           }<br />       } catch (Throwable e) {<br />           System.err.println(e);<br />       }<br />   }<br />}<br /><br />这个例子和前面那个例子非常相似。例中使用了一个新东西 Modifier，它也是一个 reflection 类，用来描述字段成员的修饰语，如“private int”。这些修饰语自身由整数描述，而且使用 Modifier.toString 来返回以“官方”顺序排列的字符串描述 (如“static”在“final”之前)。这个程序的输出是：<br /><br />name = d<br /><br />decl class = class field1<br /><br />type = double<br /><br />modifiers = private<br /><br />-----<br /><br />name = i<br /><br />decl class = class field1<br /><br />type = int<br /><br />modifiers = public static final<br /><br />-----<br /><br />name = s<br /><br />decl class = class field1<br /><br />type = class java.lang.String<br /><br />modifiers =<br /><br />-----<br /><br />和获取方法的情况一下，获取字段的时候也可以只取得在当前类中申明了的字段信息 (getDeclaredFields)，或者也可以取得父类中定义的字段 (getFields) 。<br /><br /><br />6.根据方法的名称来执行方法<br /><br />文本到这里，所举的例子无一例外都与如何获取类的信息有关。我们也可以用 reflection 来做一些其它的事情，比如执行一个指定了名称的方法。下面的示例演示了这一操作：<br /><br />import java.lang.reflect.*;<br />public class method2 {<br />   public int add(int a, int b) {<br />       return a + b;<br />   }<br />   public static void main(String args[]) {<br />       try {<br />           Class cls = Class.forName("method2");<br />           Class partypes[] = new Class[2];<br />           partypes[0] = Integer.TYPE;<br />           partypes[1] = Integer.TYPE;<br />           Method meth = cls.getMethod("add", partypes);<br />           method2 methobj = new method2();<br />           Object arglist[] = new Object[2];<br />           arglist[0] = new Integer(37);<br />           arglist[1] = new Integer(47);<br />           Object retobj = meth.invoke(methobj, arglist);<br />           Integer retval = (Integer) retobj;<br />           System.out.println(retval.intValue());<br />       } catch (Throwable e) {<br />           System.err.println(e);<br />       }<br />   }<br />}<br /><br />假如一个程序在执行的某处的时候才知道需要执行某个方法，这个方法的名称是在程序的运行过程中指定的 (例如，JavaBean 开发环境中就会做这样的事)，那么上面的程序演示了如何做到。<br /><br />上例中，getMethod 用于查找一个具有两个整型参数且名为 add 的方法。找到该方法并创建了相应的 Method 对象之后，在正确的对象实例中执行它。执行该方法的时候，需要提供一个参数列表，这在上例中是分别包装了整数 37 和 47 的两个 Integer 对象。执行方法的返回的同样是一个 Integer 对象，它封装了返回值 84。<br /><br />7.创建新的对象<br /><br />对于构造器，则不能像执行方法那样进行，因为执行一个构造器就意味着创建了一个新的对象 (准确的说，创建一个对象的过程包括分配内存和构造对象)。所以，与上例最相似的例子如下：<br /><br />import java.lang.reflect.*;<br /><br />public class constructor2 {<br />   public constructor2() {<br />   }<br /><br />   public constructor2(int a, int b) {<br />       System.out.println("a = " + a + " b = " + b);<br />   }<br /><br />   public static void main(String args[]) {<br />       try {<br />           Class cls = Class.forName("constructor2");<br />           Class partypes[] = new Class[2];<br />           partypes[0] = Integer.TYPE;<br />           partypes[1] = Integer.TYPE;<br />           Constructor ct = cls.getConstructor(partypes);<br />           Object arglist[] = new Object[2];<br />           arglist[0] = new Integer(37);<br />           arglist[1] = new Integer(47);<br />           Object retobj = ct.newInstance(arglist);<br />       } catch (Throwable e) {<br />           System.err.println(e);<br />       }<br />   }<br />}<br /><br />根据指定的参数类型找到相应的构造函数并执行它，以创建一个新的对象实例。使用这种方法可以在程序运行时动态地创建对象，而不是在编译的时候创建对象，这一点非常有价值。<br /><br />8.改变字段(域)的值<br /><br />reflection 的还有一个用处就是改变对象数据字段的值。reflection 可以从正在运行的程序中根据名称找到对象的字段并改变它，下面的例子可以说明这一点：<br /><br />import java.lang.reflect.*;<br /><br />public class field2 {<br />   public double d;<br /><br />   public static void main(String args[]) {<br />       try {<br />           Class cls = Class.forName("field2");<br />           Field fld = cls.getField("d");<br />           field2 f2obj = new field2();<br />           System.out.println("d = " + f2obj.d);<br />           fld.setDouble(f2obj, 12.34);<br />           System.out.println("d = " + f2obj.d);<br />       } catch (Throwable e) {<br />           System.err.println(e);<br />       }<br />   }<br />}<br /><br />这个例子中，字段 d 的值被变为了 12.34。<br /><br />9.使用数组<br /><br />本文介绍的 reflection 的最后一种用法是创建的操作数组。数组在 Java 语言中是一种特殊的类类型，一个数组的引用可以赋给 Object 引用。观察下面的例子看看数组是怎么工作的：<br /><br />import java.lang.reflect.*;<br /><br />public class array1 {<br />   public static void main(String args[]) {<br />       try {<br />           Class cls = Class.forName("java.lang.String");<br />           Object arr = Array.newInstance(cls, 10);<br />           Array.set(arr, 5, "this is a test");<br />           String s = (String) Array.get(arr, 5);<br />           System.out.println(s);<br />       } catch (Throwable e) {<br />           System.err.println(e);<br />       }<br />   }<br />}<br /><br />例中创建了 10 个单位长度的 String 数组，为第 5 个位置的字符串赋了值，最后将这个字符串从数组中取得并打印了出来。<br /><br />下面这段代码提供了一个更复杂的例子：<br /><br />import java.lang.reflect.*;<br /><br />public class array2 {<br />   public static void main(String args[]) {<br />       int dims[] = new int[]{5, 10, 15};<br />       Object arr = Array.newInstance(Integer.TYPE, dims);<br />       Object arrobj = Array.get(arr, 3);<br />       Class cls = arrobj.getClass().getComponentType();<br />       System.out.println(cls);<br />       arrobj = Array.get(arrobj, 5);<br />       Array.setInt(arrobj, 10, 37);<br />       int arrcast[][][] = (int[][][]) arr;<br />       System.out.println(arrcast[3][5][10]);<br />   }<br />}<br />例中创建了一个 5 x 10 x 15 的整型数组，并为处于 [3][5][10] 的元素赋了值为 37。注意，数组实际上就是数组的数组，例如，第一个 Array.get 之后，arrobj 是一个 10 x 15 的数组。进而取得其中的一个元素，即长度为 15 的数组，并使用 Array.setInt 为它的第 10 个元素赋值。<br /><br />注意创建数组时的类型是动态的，在编译时并不知道其类型<img src ="http://www.blogjava.net/liulu/aggbug/68567.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liulu/" target="_blank">刘璐</a> 2006-09-08 17:56 <a href="http://www.blogjava.net/liulu/archive/2006/09/08/68567.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是POJO</title><link>http://www.blogjava.net/liulu/archive/2006/08/28/66137.html</link><dc:creator>刘璐</dc:creator><author>刘璐</author><pubDate>Mon, 28 Aug 2006 03:35:00 GMT</pubDate><guid>http://www.blogjava.net/liulu/archive/2006/08/28/66137.html</guid><wfw:comment>http://www.blogjava.net/liulu/comments/66137.html</wfw:comment><comments>http://www.blogjava.net/liulu/archive/2006/08/28/66137.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liulu/comments/commentRss/66137.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liulu/services/trackbacks/66137.html</trackback:ping><description><![CDATA[
		<span id="lblsummary">简单的JAVA对象（Plain Old Java Objects）实际就是普通JavaBeans,使用POJO名称是为了和EJB混淆起来, 而且简称比较直接. 有一些属性及其getter setter方法的类,有时可以作为value object或dto来使用.当然,如果你有一个简单的运算属性也是可以的,但不允许有业务方法,不能携带有connection之类的</span>
<img src ="http://www.blogjava.net/liulu/aggbug/66137.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liulu/" target="_blank">刘璐</a> 2006-08-28 11:35 <a href="http://www.blogjava.net/liulu/archive/2006/08/28/66137.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>