<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    wiflish
    Loving Life! Loving Coding!
    posts - 98,comments - 98,trackbacks - 0

    很多朋友在深入的接觸 JAVA 語(yǔ)言后就會(huì)發(fā)現(xiàn)這樣兩個(gè)詞:反射 (Reflection) 和內(nèi)省 (Introspector) ,經(jīng)常搞不清楚這到底是怎么回事,在什么場(chǎng)合下應(yīng)用以及如何使用?今天把這二者放在一起介紹,因?yàn)樗鼈兌呤窍噍o相成的。

    反射

    相對(duì)而言,反射比內(nèi)省更容易理解一點(diǎn)。用一句比較白的話來(lái)概括,反射就是讓你可以通過(guò)名稱來(lái)得到對(duì)象 ( 類,屬性,方法 ) 的技術(shù)。例如我們可以通過(guò)類名來(lái)生成一個(gè)類的實(shí)例;知道了方法名,就可以調(diào)用這個(gè)方法;知道了屬性名就可以訪問(wèn)這個(gè)屬性的值。

    還是寫兩個(gè)例子讓大家更直觀的了解反射的使用方法:

    // 通過(guò)類名來(lái)構(gòu)造一個(gè)類的實(shí)例
    Class cls_str = Class.forName( "java.lang.String" );
    // 上面這句很眼熟,因?yàn)槭褂眠^(guò) JDBC 訪問(wèn)數(shù)據(jù)庫(kù)的人都用過(guò) J
    Object str = cls_str.newInstance();
    // 相當(dāng)于 String str = new String();

    // 通過(guò)方法名來(lái)調(diào)用一個(gè)方法
    String methodName = "length" ;
    Method m = cls_str.getMethod(methodName, null );
    System.out.println( "length is " + m.invoke(str, null ));
    // 相當(dāng)于 System.out.println(str.length());

    上面的兩個(gè)例子是比較常用方法。看到上面的例子就有人要發(fā)問(wèn)了:為什么要這么麻煩呢?本來(lái)一條語(yǔ)句就完成的事情干嗎要整這么復(fù)雜?沒(méi)錯(cuò),在上面的例子中確實(shí)沒(méi)有必要這么麻煩。不過(guò)你想像這樣一個(gè)應(yīng)用程序,它支持動(dòng)態(tài)的功能擴(kuò)展,也就是說(shuō)程序不重新啟動(dòng)但是可以自動(dòng)加載新的功能,這個(gè)功能使用一個(gè)具體類來(lái)表示。首先我們必須為這些功能定義一個(gè)接口類,然后我們要求所有擴(kuò)展的功能類必須實(shí)現(xiàn)我指定的接口,這個(gè)規(guī)定了應(yīng)用程序和可擴(kuò)展功能之間的接口規(guī)則,但是怎么動(dòng)態(tài)加載呢?我們必須讓應(yīng)用程序知道要擴(kuò)展的功能類的類名,比如是 test.Func1 ,當(dāng)我們把這個(gè)類名 ( 字符串 ) 告訴應(yīng)用程序后,它就可以使用我們第一個(gè)例子的方法來(lái)加載并啟用新的功能。這就是類的反射,請(qǐng)問(wèn)你有別的選擇嗎?

    ?????? 關(guān)于方法的反射建議大家看我的另外一篇文章《 利用 Turbine 的事件映射來(lái)擴(kuò)展 Struts 的功能 》,地址是: http://www.javayou.com/article/CSDN/extend_struts.html 。這篇文章詳細(xì)介紹了如果通過(guò)反射來(lái)擴(kuò)展 Struts 框架的功能。

    內(nèi)省

    內(nèi)省是 Java 語(yǔ)言對(duì) Bean 類屬性、事件的一種缺省處理方法。例如類 A 中有屬性 name, 那我們可以通過(guò) getName,setName 來(lái)得到其值或者設(shè)置新的值。通過(guò) getName/setName 來(lái)訪問(wèn) name 屬性,這就是默認(rèn)的規(guī)則。 Java 中提供了一套 API 用來(lái)訪問(wèn)某個(gè)屬性的 getter/setter 方法,通過(guò)這些 API 可以使你不需要了解這個(gè)規(guī)則(但你最好還是要搞清楚),這些 API 存放于包 java.beans 中。

    一般的做法是通過(guò)類 Introspector 來(lái)獲取某個(gè)對(duì)象的 BeanInfo 信息,然后通過(guò) BeanInfo 來(lái)獲取屬性的描述器( PropertyDescriptor ),通過(guò)這個(gè)屬性描述器就可以獲取某個(gè)屬性對(duì)應(yīng)的 getter/setter 方法,然后我們就可以通過(guò)反射機(jī)制來(lái)調(diào)用這些方法。下面我們來(lái)看一個(gè)例子,這個(gè)例子把某個(gè)對(duì)象的所有屬性名稱和值都打印出來(lái):

    /*?
    ?* Created on 2004-6-29
    ?*/

    package demo;

    import java.beans.BeanInfo;
    import java.beans.Introspector;
    import java.beans.PropertyDescriptor;

    /**
    ? * 內(nèi)省演示例子
    ? * @author liudong
    ? */

    public class IntrospectorDemo {
    ??? String name;
    ??? public static void main(String[] args) throws Exception{
    ??????? IntrospectorDemo demo = new IntrospectorDemo();
    ??????? demo.setName( "Winter Lau" ); ???????

    ??????? // 如果不想把父類的屬性也列出來(lái)的話,
    ??????? // getBeanInfo 的第二個(gè)參數(shù)填寫父類的信息
    ??????? BeanInfo bi = Introspector.getBeanInfo(demo.getClass(), Object. class );
    ??????? PropertyDescriptor[] props = bi.getPropertyDescriptors();
    ??????? for ( int i=0;i<props.length;i++){
    ??????????? System.out.println(props[i].getName()+ "=" +
    ??????????????????? props[i].getReadMethod().invoke(demo, null ));
    ??????? }

    ??? } ???

    ??? public String getName() {
    ??????? return name;
    ??? }

    ??? public void setName(String name) {
    ??????? this .name = name;
    ??? }
    }

    Web 開發(fā)框架 Struts 中的 FormBean 就是通過(guò)內(nèi)省機(jī)制來(lái)將表單中的數(shù)據(jù)映射到類的屬性上,因此要求 FormBean 的每個(gè)屬性要有 getter/setter 方法。但也并不總是這樣,什么意思呢?就是說(shuō)對(duì)一個(gè) Bean 類來(lái)講,我可以沒(méi)有屬性,但是只要有 getter/setter 方法中的其中一個(gè),那么 Java 的內(nèi)省機(jī)制就會(huì)認(rèn)為存在一個(gè)屬性,比如類中有方法 setMobile ,那么就認(rèn)為存在一個(gè) mobile 的屬性,這樣可以方便我們把 Bean 類通過(guò)一個(gè)接口來(lái)定義而不用去關(guān)心具體實(shí)現(xiàn),不用去關(guān)心 Bean 中數(shù)據(jù)的存儲(chǔ)。比如我們可以把所有的 getter/setter 方法放到接口里定義,但是真正數(shù)據(jù)的存取則是在具體類中去實(shí)現(xiàn),這樣可提高系統(tǒng)的擴(kuò)展性。

    總結(jié)

    Java 的反射以及內(nèi)省應(yīng)用到程序設(shè)計(jì)中去可以大大的提供程序的智能化和可擴(kuò)展性。有很多項(xiàng)目都是采取這兩種技術(shù)來(lái)實(shí)現(xiàn)其核心功能,例如我們前面提到的 Struts ,還有用于處理 XML 文件的 Digester 項(xiàng)目,其實(shí)應(yīng)該說(shuō)幾乎所有的項(xiàng)目都或多或少的采用這兩種技術(shù)。在實(shí)際應(yīng)用過(guò)程中二者要相互結(jié)合方能發(fā)揮真正的智能化以及高度可擴(kuò)展性。

    posted on 2007-03-05 17:40 想飛的魚 閱讀(8148) 評(píng)論(2)  編輯  收藏 所屬分類: java

    FeedBack:
    # re: 【轉(zhuǎn)】JAVA的內(nèi)省(introspector)與反射(reflection)
    2007-03-15 10:00 | NiceShoot
    寫的好,用最簡(jiǎn)單的例子解釋清楚了我心中的疑惑。謝謝  回復(fù)  更多評(píng)論
      
    # re: 【轉(zhuǎn)】JAVA的內(nèi)省(introspector)與反射(reflection)[未登錄](méi)
    2012-12-18 17:07 | javaer
    寫的好~  回復(fù)  更多評(píng)論
      
    主站蜘蛛池模板: AV无码免费永久在线观看| 美女又黄又免费的视频| 亚洲综合精品香蕉久久网97| 久久综合日韩亚洲精品色| 亚洲免费在线视频| 亚洲福利视频一区二区三区| 亚洲欧洲自拍拍偷综合| 亚洲AV成人无码天堂| 在线观看亚洲AV日韩A∨| 亚洲成a人片在线观看天堂无码 | 亚洲电影一区二区三区| 久久精品国产亚洲AV电影| 亚洲一区二区三区91| 色偷偷尼玛图亚洲综合| 日韩精品免费一线在线观看| 中文字幕免费在线播放| 色欲A∨无码蜜臀AV免费播| 国产精品成人观看视频免费| 久久这里只有精品国产免费10| 日本v片免费一区二区三区| 亚洲?V无码乱码国产精品| 亚洲中文字幕不卡无码| 亚洲毛片在线观看| 亚洲三级高清免费| 羞羞漫画页面免费入口欢迎你| 中文字幕免费观看视频| 麻豆高清免费国产一区| 成人午夜视频免费| 亚洲精品国自产拍在线观看| 亚洲人成网址在线观看| 亚洲色偷偷偷综合网| 一区二区在线视频免费观看| 久久久久国产免费| 女人被免费视频网站| 青青草原亚洲视频| 亚洲熟妇无码久久精品| 国产在亚洲线视频观看| 久久久久久久99精品免费| 国内自产少妇自拍区免费| 亚洲码国产精品高潮在线| 亚洲中文字幕无码av在线|