2008年11月17日

            上一篇中,通過例子我們知道了如何利用反射機制創建對象,獲得類變量和調用方法等。創建對象的語句是  Class cla = Class.forName(type);    Object obj = cla.newInstance(); 這里newInstance()實際上是使用了該類的默認無參構造方法。如果我們要調用其它的構造方法就要稍微復雜一點。比如我們要創建一個StringBuffer對象,用new 操作符應該是StringBuffer br = new StringBuffer("example");用反射機制則要有以下步驟。
          首先,獲得StringBuffer類的描述。
          Class cla = Class.forName("java.lang.StringBuffer");
          其次,要創建參數類型數組Class[] 。
          Class[] paraTypes = new Class[1];paraTypes[0]=String.class;
          然后,通過cla 和 paraTypes 獲得Constructor 對象。
          Constructor constructor = cla.getConstructor(paraTypes);
          接著,創建傳入的參數列表Object[]。
          Object[] paraLists = new Object[1]; paraLists[0]="color";
          最后,得到我們所要得對象。Object obj = constructor.newInstance(paraLists);
          如果我們paraTypes及paraLists設為null或長度為0,就可以用上述步驟調用StringBuffer的無參構造方法。類似地,我們可以調用對象中的有參方法。比如我們做如下操作br.insert(4, 'u');用反射機制實現如下。
          Class[] paratypes = new Class[]{int.class,char.class};
          Method method = cla.getMethod("insert", paratypes);
          Object[] paralists = new Object[]{4,'u'};
          method.invoke(obj, paralists);
           反射機制給予我們運行時才確定對象類型的便利,然而它也有顯著的缺點。
          1,代碼笨拙冗長。比如本來一句br.insert(4, 'u');可以解決的問題現在要用到四句。
          2,損失了編譯時類型檢查的好處。這使得你要對付更多的異常。
          3,性能損失。用反射機制運行的時間更久。
            <<Effective Java >>中給出的建議是“普通應用不應在運行時刻以映像方式訪問對象,只是在很有限的情況下
          使用“。那么在什么地方會用到反射機制呢。已有的較熟悉應用是我們的IDE及一些框架。比如eclipse,編程時ctrl+space彈出的建議就是用到反射機制。比如Spring讀取配置文件后生成對應的對象。還有RPC系統也會用到。對于一般的應用軟件,你可以在工廠方法中用到它。
              

            參考文章:
          <Effective Java> 第一版 35條
          <侯捷談Java反射機制>
          JAVA API
                                                                                                                                     

          posted @ 2008-11-20 15:27 JFire 閱讀(1437) | 評論 (0)編輯 收藏
           
            下面我以顧客買相機為例來說明Java反射機制的應用。例子中涉及的類和接口有:
          Camera接口:定義了takePhoto()方法。
          Camera01類:一種照相機的類型,實現Camera接口。
          Camera02類:另一種照相機的類型,實現Camera接口。
          Seller類:賣照相機。
          Customer類:買相機,有main方法。
          所有類都放在com包里
            程序如下:
          public interface Camera {
              //聲明照相機必須可以拍照
           public void takePhoto();
          }
          public class Camera01 implements Camera {
           private final int prefixs =300;//300萬象素
           private final double optionZoom=3.5; //3.5倍變焦
           public void takePhoto() {
            System.out.println("Camera01 has taken a photo");
           }
          }
          類似的有
          public class Camera02 implements Camera {
           private final int prefixs =400;
           private final double optionZoom=5;
           public void takePhoto() {
            System.out.println("Camera02 has taken a photo");
           }
          }
          顧客出場了
          public class Customer {
           public static void main(String[] args){
            //找到一個售貨員 
            Seller seller = new Seller();
            //向售貨員詢問兩種相機的信息
            seller.getDescription("com.Camera01");
            seller.getDescription("com.Camera02");
            //覺得Camera02比較好,叫售貨員拿來看
            Camera camera =(Camera)seller.getCamera("com.Camera02");
            //讓售貨員拍張照試一下
            seller.testFuction(camera, "takePhoto");
           }
          }
          Seller類通過Java反射機制實現
          import java.lang.reflect.Field;
          import java.lang.reflect.Method;
          public class Seller {
           //向顧客描述商品信息
           public void getDescription(String type){
            try {
             Class cla = Class.forName(type);
             //生成一個實例對象,在編譯時我們并不知道obj是什么類型。
             Object obj = cla.newInstance();
             //獲得type類型所有已定義類變量及方法。
             Field[] fileds = cla.getDeclaredFields();
             Method[]methods = cla.getDeclaredMethods();
             System.out.println("The arguments of this Camera is:");
             for(int i=0;i<fileds.length;i++){
              fileds[i].setAccessible(true);
              //輸出類變量的定義及obj實例中對應的值
              System.out.println(fileds[i]+":"+fileds[i].get(obj));
             }
             System.out.println("The function of this Camera:");
             for(int i=0;i<methods.length;i++){
              //輸出類中方法的定義
              System.out.println(methods[i]);
             }
             System.out.println();
            } catch (Exception e) {
             System.out.println("Sorry , no such type");
            }
           }
           //使用商品的某個功能
           public void testFuction(Object obj,String function){
            try {
             Class cla = obj.getClass();
             //獲得cla類中定義的無參方法。
             Method m = cla.getMethod(function, null);
             //調用obj中名為function的無參方法。
             m.invoke(obj, null);
            } catch (Exception e) { 
             System.out.println("Sorry , no such function");
             
            } 
           }
           //拿商品給顧客
           public Object getCamera(String type){
            try {
             Class cla = Class.forName(type);
             Object obj = cla.newInstance();
             return obj;
            } catch (Exception e) { 
             System.out.println("Sorry , no such type");
             return null;
            } 
           }
          }
            程序到此結束,下一篇我將對程序進行分析,并補充一些內容。
          posted @ 2008-11-17 14:30 JFire 閱讀(1840) | 評論 (2)編輯 收藏
           
               摘要: Java 反射機制是指Java程序可以在執行期載入,探知,使用編譯期間完全未知的classes  閱讀全文
          posted @ 2008-11-17 13:30 JFire 閱讀(1610) | 評論 (0)編輯 收藏
           
          主站蜘蛛池模板: 教育| 昭苏县| 荣成市| 鄂尔多斯市| 洮南市| 庄浪县| 合水县| 汤原县| 汉川市| 平顺县| 梁河县| 虎林市| 柳江县| 花莲市| 诸暨市| 大连市| 溧阳市| 临西县| 东乡县| 建昌县| 保定市| 垫江县| 胶南市| 旅游| 临武县| 林州市| 和平县| 安达市| 东乡族自治县| 富川| 卢氏县| 孟连| 芦溪县| 凤庆县| 屏南县| 青神县| 丽江市| 吴堡县| 广灵县| 玉屏| 延边|