J2EE學(xué)習(xí)筆記
          我們的失落……
          posts - 13,comments - 1,trackbacks - 0

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

          反射

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

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

          // 通過類名來構(gòu)造一個類的實例
          Class cls_str = Class.forName( "java.lang.String" );
          // 上面這句很眼熟,因為使用過 JDBC 訪問數(shù)據(jù)庫的人都用過 J
          Object str = cls_str.newInstance();
          // 相當(dāng)于 String str = new String(); 


          // 通過方法名來調(diào)用一個方法
          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()); 


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

          內(nèi)省

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

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

          /* 
           * 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" );         

                  
          // 如果不想把父類的屬性也列出來的話,
                  
          // 那 getBeanInfo 的第二個參數(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就是通過內(nèi)省機(jī)制來將表單中的數(shù)據(jù)映射到類的屬性上,因此要求FormBean的每個屬性要有g(shù)etter/setter方法。但也并不總是這樣,什么意思呢?就是說對一個Bean類來講,我可以沒有屬性,但是只要有g(shù)etter/setter方法中的其中一個,那么Java的內(nèi)省機(jī)制就會認(rèn)為存在一個屬性,比如類中有方法setMobile,那么就認(rèn)為存在一個mobile的屬性,這樣可以方便我們把Bean類通過一個接口來定義而不用去關(guān)系具體實現(xiàn),不用去關(guān)系Bean中數(shù)據(jù)的存儲。比如我們可以把所有的getter/setter方法放到接口里定義,但是真正數(shù)據(jù)的存取則是在具體類中去實現(xiàn),這樣可提高系統(tǒng)的擴(kuò)展性。

          總結(jié)

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

          posted on 2010-02-04 13:42 J2EE學(xué)習(xí)筆記 閱讀(376) 評論(1)  編輯  收藏 所屬分類: 轉(zhuǎn)載java

          FeedBack:
          # re: [轉(zhuǎn)]JAVA語言的反射(Reflection)和內(nèi)省(Introspector)
          2010-02-22 09:32 | leeo
          哈哈,林林,你很行嘛~:)  回復(fù)  更多評論
            
          主站蜘蛛池模板: 共和县| 桂东县| 谷城县| 株洲县| 宿松县| 西藏| 工布江达县| 雅安市| 沧州市| 大兴区| 奇台县| 定安县| 六安市| 和林格尔县| 安徽省| 武平县| 徐水县| 白银市| 三明市| 黑山县| 洛浦县| 平原县| 尼木县| 桐庐县| 皋兰县| 平安县| 灵璧县| 郎溪县| 久治县| 昌吉市| 永新县| 石楼县| 天门市| 津市市| 丹寨县| 宁津县| 哈尔滨市| 衡南县| 牟定县| 阿坝县| 永康市|