posts - 2,  comments - 2,  trackbacks - 0
            2007年5月16日

          Java looking at Java

             Java的一個(gè)很不尋常的能力,它允許一個(gè)程序檢查自己
             你可以確定一個(gè)對(duì)象所屬的類型
             你可以查看一個(gè)類的全部?jī)?nèi)容,它們的訪問(wèn)修飾符、父類、字段、構(gòu)造函數(shù)、方法
             你可以查看一個(gè)接口的內(nèi)容
             即使在編寫(xiě)代碼的時(shí)候你不知道事物的名字你也可以做到:
             創(chuàng)建一個(gè)類的實(shí)例
             取得和設(shè)置一個(gè)實(shí)例的變量
             調(diào)用一個(gè)對(duì)象的一個(gè)方法
             創(chuàng)建和操作數(shù)組

             我猜它之所以被稱為“反射”是因?yàn)樗试S一個(gè)Java應(yīng)用程序像“在鏡子里”看到自己一樣。

          What is reflection for?

             在“平常”的程序中你可能用不到反射
             如果你是在使用應(yīng)用程序來(lái)操作應(yīng)用程序,那你就需要使用反射了。
             典型的應(yīng)用:
             一個(gè)類型查看器
             一個(gè)調(diào)試程序
             一個(gè)GUI創(chuàng)建器
             一個(gè)IDE,比喻說(shuō)BlueJ或Eclipse

          IDE

             有需要的IDE本身就是用Java編寫(xiě)的—它們可以做什么?
             編譯一個(gè)程序(簡(jiǎn)單—只是一個(gè)系統(tǒng)調(diào)用)
             編譯后加載進(jìn)你的系統(tǒng)
             弄清楚你都有些什么類,它們的構(gòu)造函數(shù)和方法
             執(zhí)行你的main方法
             替你創(chuàng)建對(duì)象,即使現(xiàn)在沒(méi)有運(yùn)行main方法
             為對(duì)象傳遞信息,并顯示結(jié)果
             這些所有的功能,除了編譯都是使用反射做到的

          Class 類

             要發(fā)現(xiàn)一個(gè)具體的類的信息,首先要取得它的Class 對(duì)象
             如果你有一個(gè) obj 對(duì)象,你可以通過(guò)下面的方式來(lái)取得它的class對(duì)象
          Class c = obj.getClass();
             你可以通過(guò)一個(gè)class的實(shí)例c 取得它的父類
          Class sup = c.getSuperclass();
             如果你已經(jīng)知道一個(gè)類在編譯時(shí)候的名字 (比喻說(shuō), Button) ,你可以通過(guò)下面這樣的簡(jiǎn)單方法取得class對(duì)象
          Class c = Button.class;
             如果你知道一個(gè)類在運(yùn)行期的名字(比喻說(shuō),一個(gè)String類型變量str),你可以通過(guò)下面的方法取得類對(duì)象
          Class c = Class.forName(str);

          取得類的名字

             如果你已經(jīng)有了一個(gè)class對(duì)象c,你可以通過(guò)下面的方法取得類的名字 c.getName()
             getName 取得類的全路徑名字; 比喻說(shuō),
              Class c = Button.class;
              String s = c.getName();
              System.out.println(s);
          會(huì)輸出
              java.awt.Button
             類 Class 和它的方法都是在 java.lang中,所以不需要使用import使其可用。

          取得所有的父類

             getSuperclass() 返回一個(gè) Class 對(duì)象 (或者 null 如果你在 Object上使用的話,它是沒(méi)有父類的 )

             下面的代碼來(lái)自Sun的入門(mén)指南:

               static void printSuperclasses(Object o) {
               Class subclass = o.getClass();
               Class superclass = subclass.getSuperclass();
               while (superclass != null) {
               String className = superclass.getName();
               System.out.println(className);
               subclass = superclass;
               superclass = subclass.getSuperclass();
                    }
          }

          取得類的修飾符I

             Class對(duì)象有一個(gè)實(shí)例方法 getModifiers() ,它返回一個(gè)int型的值

             為了“解釋” int 型的結(jié)果,我們要用到Modifier類的一些方法,它們位于 java.lang.reflect, 所以:

              import java.lang.reflect.*;

             現(xiàn)在我們就可以做下面的事情了:

          if (Modifier.isPublic(m)) {
              System.out.println("public");
          }

          取得類的修飾符II

             Modifier 包含下面的一些方法 (只列出部分):
             public static boolean isAbstract(int)
             public static boolean isFinal(int)
             public static boolean isInterface(int)
             public static boolean isPrivate(int)
             public static boolean isProtected(int)
             public static boolean isPublic(int)
             public static String toString(int)
             這會(huì)返回一個(gè)如下所示的字符串
          "public final synchronized strictfp"

          取得接口

             一個(gè)類可以實(shí)現(xiàn)0個(gè)或多個(gè)接口
             getInterfaces() 返回一個(gè) Class 對(duì)象的數(shù)組
             這些是類實(shí)現(xiàn)的一些接口
             下面的代碼來(lái)自Sun的入門(mén)指南:
             static void printInterfaceNames(Object o) {
              Class c = o.getClass();
              Class[ ] theInterfaces = c.getInterfaces();
              for (int i = 0; i < theInterfaces.length; i++) {
                 String interfaceName = theInterfaces[i].getName();
                 System.out.println(interfaceName);
              }
          }
             注意:零長(zhǎng)度數(shù)組在Java中是合法的

          判斷類和接口

             Class 類既能代表類也能代表接口
             要確定一個(gè)給定的 Class 對(duì)象 c 是否是一個(gè)是接口,可以使用 c.isInterface()
             要研究class對(duì)象的更多內(nèi)容的話,你可以使用下面這些方法:
             getModifiers()
             getFields()    // "fields" == "instance variables"
             getConstructors()
             getMethods()
             isArray()

          取得字段

             public Field[] getFields() throws SecurityException
             返回一個(gè)public的字段數(shù)組 (變量)
             數(shù)組的長(zhǎng)度允許是0
             字段的組織順序沒(méi)有任何的規(guī)則
             本身定義的和通過(guò)繼承的來(lái)的變量都被返回,但是不包含 static 變量
             public Field getField(String name)
              throws NoSuchFieldException, SecurityException
             返回指定名稱的 public 字段
             如果沒(méi)有直接的字段被發(fā)現(xiàn),那父類或者接口被遞歸的查詢

          使用字段 I

             如果 f 是 Field 對(duì)象, 那么
             f.getName() 返回字段的簡(jiǎn)單的名字
             f.getType() 返回字段的類型 (Class)
             f.getModifiers() 返回字段的Modifier
             f.toString() 返回一個(gè)包含了訪問(wèn)修飾符,類型,和全路徑字段名字的字符串
             例如: public  java.lang.String  Person.name
             f.getDeclaringClass() 返回定義字段的類的 Class 對(duì)象

          使用字段 II

             obj 對(duì)象的字段的值可以使用下面的方式進(jìn)行操作:
             boolean f.getBoolean(obj),
          int f.getInt(obj),
          double f.getDouble(obj),
          等等,返回字段的值,假設(shè)它是那個(gè)類型或者可以擴(kuò)展成那個(gè)型
             Object f.get(obj) 返回一個(gè)字段的值,假設(shè)它是一個(gè)對(duì)象
             void f.set(obj, value),
          void f.setBoolean(obj, bool),
          void f.setInt(obj, i),
          void f.getDouble(obj, d),等等,設(shè)置一個(gè)字段的值

          構(gòu)造函數(shù)

             如果 c 是一個(gè)構(gòu)造函數(shù),那么
             c.getName() 返回構(gòu)造函數(shù)的名字,與類的名字完全一致
             c.getDeclaringClass() 返回構(gòu)造函數(shù)被聲明的 Class 對(duì)象
             c.getModifiers() 返回構(gòu)造函數(shù)的 Modifier
             c.getParameterTypes() 返回一個(gè)Class 對(duì)象數(shù)組, 以聲明的順序
             c.newInstance(Object[] initargs) 創(chuàng)建被返回一個(gè)c類的實(shí)例對(duì)象
             需要使用簡(jiǎn)單類型的地方會(huì)被自動(dòng)的轉(zhuǎn)換

          方法

             public Method[] getMethods()
                    throws SecurityException
             返回一個(gè) Method 對(duì)象數(shù)組
             返回的是類或接口的 public 成員方法,同時(shí)也包含繼承的來(lái)的方法
             返回的方法沒(méi)有任何的順序
             public Method getMethod(String name,
                                                 Class[] parameterTypes)
          throws NoSuchMethodException, SecurityException

          Method 中的方法 I

             getDeclaringClass()
             返回一個(gè)Class 對(duì)象,它代表了這個(gè)Method 對(duì)象所被聲明的類或接口
             getName()
             返回代表這個(gè)Method 對(duì)象的名字,以字符串的方式
             getModifiers()
             返回代表這個(gè)Method 對(duì)象的修飾符,以整型的方式
             getParameterTypes()
             返回這個(gè)Method 對(duì)象所需要的參數(shù)的 Class 對(duì)象數(shù)組,以聲明的順序出現(xiàn)

          Method 中的方法 II

             getReturnType()
             返回代表這個(gè)Method 對(duì)象的返回值的一個(gè) Class對(duì)象名字
             toString()
             返回一個(gè)代表這個(gè)Method 對(duì)象的字符串,通常情況下會(huì)很長(zhǎng)
             public Object invoke(Object obj, Object[] args)
             在特定的對(duì)象上使用特定的參數(shù),執(zhí)行這個(gè)Method對(duì)象所代表的方法
             個(gè)別的參數(shù)會(huì)被自動(dòng)轉(zhuǎn)換來(lái)實(shí)現(xiàn)一些對(duì)基本數(shù)據(jù)類型的需要

          數(shù)組 I

             可以采用下面的方法來(lái)判斷一個(gè)obj 對(duì)象是不是一個(gè)數(shù)組
             Class c = obj.getClass();
             c.isArray()
             要取得這個(gè)數(shù)組的元素的類型可以使用,
             c.getComponentType()
             如果c不是一個(gè)數(shù)組的話會(huì)返回一個(gè) null
             在java.lang.reflect 包中包含了一個(gè) Array 類,它提供了一些 static 方法來(lái)操作數(shù)組

          數(shù)組 II

             要?jiǎng)?chuàng)建一個(gè)數(shù)組,
              Array.newInstance(Class componentType, int size)
             返回一個(gè)新創(chuàng)建的數(shù)組Object對(duì)象,
             你可以把它造型成你想要的類型
             componentType 本身就可以是一個(gè)數(shù)組
             這會(huì)產(chǎn)生一個(gè)多維數(shù)組
             維數(shù)的最大限制一般在255
             Array.newInstance(Class componentType, int[] size)
             返回一個(gè)新創(chuàng)建的多維數(shù)組Object對(duì)象 (使用 size.length 維度)

          數(shù)組 III

             得到數(shù)組元素的值
             Array.get(Object array, int index) 返回一個(gè) Object
             Array.getBoolean(Object array, int index) 返回一個(gè) boolean
             Array.getByte(Object array, int index) 返回一個(gè) byte
             等等.
             往數(shù)組中保存值,
             Array.set(Object array, int index, Object value)
             Array.setBoolean(Object array, int index, boolean z)
             Array.setByte(Object array, int index, byte b)
             等等.

          結(jié)束語(yǔ)

             很多方法都有自己的異常,我在這里沒(méi)有描述
             要查看詳情,你參照J(rèn)ava API
             反射在“平常”的程序中用不到,可是你真的需要它的時(shí)候卻是不可替代的。
             一個(gè)相關(guān)的話題-類的加載器(class loaders)—Java把需要的類讀進(jìn)內(nèi)存
             你可以編寫(xiě)你自己的加載器
             這是別的大多數(shù)語(yǔ)言不包含的一種功能
          posted @ 2007-05-16 19:20 魷魚(yú) 閱讀(616) | 評(píng)論 (0)編輯 收藏
          僅列出標(biāo)題  
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(4)

          隨筆檔案

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 惠水县| 邢台市| 拉萨市| 民丰县| 民县| 康平县| 西盟| 简阳市| 辽宁省| 濮阳县| 万安县| 巨鹿县| 盐池县| 广宗县| 云林县| 涞源县| 襄汾县| 客服| 嘉义市| 仲巴县| 德格县| 天台县| 澳门| 绍兴县| 淮阳县| 金山区| 都江堰市| 湘潭县| 科技| 柳州市| 永和县| 衡阳县| 湾仔区| 崇义县| 手游| 河津市| 淄博市| 全椒县| 文成县| 五原县| 宝山区|