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

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

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

    銀色幻想

    常用鏈接

    統(tǒng)計(jì)

    積分與排名

    學(xué)習(xí)交流

    最新評(píng)論

    Java Reflection

    Reflection 是 Java 程序開(kāi)發(fā)語(yǔ)言的特征之一,它允許運(yùn)行中的 Java 程序?qū)ψ陨磉M(jìn)行檢查,或者說(shuō)“自審”,并能直接操作程序的內(nèi)部屬性。例如,使用它能獲得 Java 類(lèi)中各成員的名稱(chēng)并顯示出來(lái)。

    Java 的這一能力在實(shí)際應(yīng)用中也許用得不是很多,但是在其它的程序設(shè)計(jì)語(yǔ)言中根本就不存在這一特性。例如,Pascal、C 或者 C++ 中就沒(méi)有辦法在程序中獲得函數(shù)定義相關(guān)的信息。

    JavaBean 是 reflection 的實(shí)際應(yīng)用之一,它能讓一些工具可視化的操作軟件組件。這些工具通過(guò) reflection 動(dòng)態(tài)的載入并取得 Java 組件(類(lèi)) 的屬性。



    1. 一個(gè)簡(jiǎn)單的例子

    考慮下面這個(gè)簡(jiǎn)單的例子,讓我們看看 reflection 是如何工作的。

    import java.lang.reflect.*;
    public class DumpMethods {
       public static void main(String args[]) {
           try {
               Class c = Class.forName(args[0]);
               Method m[] = c.getDeclaredMethods();
               for (int i = 0; i < m.length; i++)
                   System.out.println(m[i].toString());
           } catch (Throwable e) {
               System.err.println(e);
           }
       }
    }

    按如下語(yǔ)句執(zhí)行:

    java DumpMethods java.util.Stack

    它的結(jié)果輸出為:

    public java.lang.Object java.util.Stack.push(java.lang.Object)

    public synchronized java.lang.Object java.util.Stack.pop()

    public synchronized java.lang.Object java.util.Stack.peek()

    public boolean java.util.Stack.empty()

    public synchronized int java.util.Stack.search(java.lang.Object)

    這樣就列出了java.util.Stack 類(lèi)的各方法名以及它們的限制符和返回類(lèi)型。

    這個(gè)程序使用 Class.forName 載入指定的類(lèi),然后調(diào)用 getDeclaredMethods 來(lái)獲取這個(gè)類(lèi)中定義了的方法列表。java.lang.reflect.Methods 是用來(lái)描述某個(gè)類(lèi)中單個(gè)方法的一個(gè)類(lèi)。

    2.開(kāi)始使用 Reflection

    用于 reflection 的類(lèi),如 Method,可以在 java.lang.relfect 包中找到。使用這些類(lèi)的時(shí)候必須要遵循三個(gè)步驟:第一步是獲得你想操作的類(lèi)的 java.lang.Class 對(duì)象。在運(yùn)行中的 Java 程序中,用 java.lang.Class 類(lèi)來(lái)描述類(lèi)和接口等。

    下面就是獲得一個(gè) Class 對(duì)象的方法之一:

    Class c = Class.forName("java.lang.String");

    這條語(yǔ)句得到一個(gè) String 類(lèi)的類(lèi)對(duì)象。還有另一種方法,如下面的語(yǔ)句:

    Class c = int.class;

    或者

    Class c = Integer.TYPE;

    它們可獲得基本類(lèi)型的類(lèi)信息。其中后一種方法中訪(fǎng)問(wèn)的是基本類(lèi)型的封裝類(lèi) (如 Integer) 中預(yù)先定義好的 TYPE 字段。

    第二步是調(diào)用諸如 getDeclaredMethods 的方法,以取得該類(lèi)中定義的所有方法的列表。

    一旦取得這個(gè)信息,就可以進(jìn)行第三步了——使用 reflection API 來(lái)操作這些信息,如下面這段代碼:

    Class c = Class.forName("java.lang.String");

    Method m[] = c.getDeclaredMethods();

    System.out.println(m[0].toString());

    它將以文本方式打印出 String 中定義的第一個(gè)方法的原型。

    在下面的例子中,這三個(gè)步驟將為使用 reflection 處理特殊應(yīng)用程序提供例證。

    模擬 instanceof 操作符

    得到類(lèi)信息之后,通常下一個(gè)步驟就是解決關(guān)于 Class 對(duì)象的一些基本的問(wèn)題。例如,Class.isInstance 方法可以用于模擬 instanceof 操作符:

    class A {
    }

    public class instance1 {
       public static void main(String args[]) {
           try {
               Class cls = Class.forName("A");
               boolean b1 = cls.isInstance(new Integer(37));
               System.out.println(b1);
               boolean b2 = cls.isInstance(new A());
               System.out.println(b2);
           } catch (Throwable e) {
               System.err.println(e);
           }
       }
    }

    在這個(gè)例子中創(chuàng)建了一個(gè) A 類(lèi)的 Class 對(duì)象,然后檢查一些對(duì)象是否是 A 的實(shí)例。Integer(37) 不是,但 new A() 是。

    3.找出類(lèi)的方法

    找出一個(gè)類(lèi)中定義了些什么方法,這是一個(gè)非常有價(jià)值也非常基礎(chǔ)的 reflection 用法。下面的代碼就實(shí)現(xiàn)了這一用法:

    import java.lang.reflect.*;

    public class method1 {
       private int f1(Object p, int x) throws NullPointerException {
           if (p == null)
               throw new NullPointerException();
           return x;
       }

       public static void main(String args[]) {
           try {
               Class cls = Class.forName("method1");
               Method methlist[] = cls.getDeclaredMethods();
               for (int i = 0; i < methlist.length; i++) {
                   Method m = methlist[i];
                   System.out.println("name = " + m.getName());
                   System.out.println("decl class = " + m.getDeclaringClass());
                   Class pvec[] = m.getParameterTypes();
                   for (int j = 0; j < pvec.length; j++)
                       System.out.println("param #" + j + " " + pvec[j]);
                   Class evec[] = m.getExceptionTypes();
                   for (int j = 0; j < evec.length; j++)
                       System.out.println("exc #" + j + " " + evec[j]);
                   System.out.println("return type = " + m.getReturnType());
                   System.out.println("-----");
               }
           } catch (Throwable e) {
               System.err.println(e);
           }
       }
    }

    這個(gè)程序首先取得 method1 類(lèi)的描述,然后調(diào)用 getDeclaredMethods 來(lái)獲取一系列的 Method 對(duì)象,它們分別描述了定義在類(lèi)中的每一個(gè)方法,包括 public 方法、protected 方法、package 方法和 private 方法等。如果你在程序中使用 getMethods 來(lái)代替 getDeclaredMethods,你還能獲得繼承來(lái)的各個(gè)方法的信息。

    取得了 Method 對(duì)象列表之后,要顯示這些方法的參數(shù)類(lèi)型、異常類(lèi)型和返回值類(lèi)型等就不難了。這些類(lèi)型是基本類(lèi)型還是類(lèi)類(lèi)型,都可以由描述類(lèi)的對(duì)象按順序給出。

    輸出的結(jié)果如下:

    name = f1

    decl class = class method1

    param #0 class java.lang.Object

    param #1 int

    exc #0 class java.lang.NullPointerException

    return type = int

    -----

    name = main

    decl class = class method1

    param #0 class [Ljava.lang.String;

    return type = void

    -----


    4.獲取構(gòu)造器信息

    獲取類(lèi)構(gòu)造器的用法與上述獲取方法的用法類(lèi)似,如:

    import java.lang.reflect.*;

    public class constructor1 {
       public constructor1() {
       }

       protected constructor1(int i, double d) {
       }

       public static void main(String args[]) {
           try {
               Class cls = Class.forName("constructor1");
               Constructor ctorlist[] = cls.getDeclaredConstructors();
               for (int i = 0; i < ctorlist.length; i++) {
                   Constructor ct = ctorlist[i];
                   System.out.println("name = " + ct.getName());
                   System.out.println("decl class = " + ct.getDeclaringClass());
                   Class pvec[] = ct.getParameterTypes();
                   for (int j = 0; j < pvec.length; j++)
                       System.out.println("param #" + j + " " + pvec[j]);
                   Class evec[] = ct.getExceptionTypes();
                   for (int j = 0; j < evec.length; j++)
                       System.out.println("exc #" + j + " " + evec[j]);
                   System.out.println("-----");
               }
           } catch (Throwable e) {
               System.err.println(e);
           }
       }
    }

    這個(gè)例子中沒(méi)能獲得返回類(lèi)型的相關(guān)信息,那是因?yàn)闃?gòu)造器沒(méi)有返回類(lèi)型。

    這個(gè)程序運(yùn)行的結(jié)果是:

    name = constructor1

    decl class = class constructor1

    -----

    name = constructor1

    decl class = class constructor1

    param #0 int

    param #1 double

    -----

    5.獲取類(lèi)的字段(域)

    找出一個(gè)類(lèi)中定義了哪些數(shù)據(jù)字段也是可能的,下面的代碼就在干這個(gè)事情:


    import java.lang.reflect.*;

    public class field1 {
       private double d;
       public static final int i = 37;
       String s = "testing";

       public static void main(String args[]) {
           try {
               Class cls = Class.forName("field1");
               Field fieldlist[] = cls.getDeclaredFields();
               for (int i = 0; i < fieldlist.length; i++) {
                   Field fld = fieldlist[i];
                   System.out.println("name = " + fld.getName());
                   System.out.println("decl class = " + fld.getDeclaringClass());
                   System.out.println("type = " + fld.getType());
                   int mod = fld.getModifiers();
                   System.out.println("modifiers = " + Modifier.toString(mod));
                   System.out.println("-----");
               }
           } catch (Throwable e) {
               System.err.println(e);
           }
       }
    }

    這個(gè)例子和前面那個(gè)例子非常相似。例中使用了一個(gè)新東西 Modifier,它也是一個(gè) reflection 類(lèi),用來(lái)描述字段成員的修飾語(yǔ),如“private int”。這些修飾語(yǔ)自身由整數(shù)描述,而且使用 Modifier.toString 來(lái)返回以“官方”順序排列的字符串描述 (如“static”在“final”之前)。這個(gè)程序的輸出是:

    name = d

    decl class = class field1

    type = double

    modifiers = private

    -----

    name = i

    decl class = class field1

    type = int

    modifiers = public static final

    -----

    name = s

    decl class = class field1

    type = class java.lang.String

    modifiers =

    -----

    和獲取方法的情況一下,獲取字段的時(shí)候也可以只取得在當(dāng)前類(lèi)中申明了的字段信息 (getDeclaredFields),或者也可以取得父類(lèi)中定義的字段 (getFields) 。


    6.根據(jù)方法的名稱(chēng)來(lái)執(zhí)行方法

    文本到這里,所舉的例子無(wú)一例外都與如何獲取類(lèi)的信息有關(guān)。我們也可以用 reflection 來(lái)做一些其它的事情,比如執(zhí)行一個(gè)指定了名稱(chēng)的方法。下面的示例演示了這一操作:

    import java.lang.reflect.*;
    public class method2 {
       public int add(int a, int b) {
           return a + b;
       }
       public static void main(String args[]) {
           try {
               Class cls = Class.forName("method2");
               Class partypes[] = new Class[2];
               partypes[0] = Integer.TYPE;
               partypes[1] = Integer.TYPE;
               Method meth = cls.getMethod("add", partypes);
               method2 methobj = new method2();
               Object arglist[] = new Object[2];
               arglist[0] = new Integer(37);
               arglist[1] = new Integer(47);
               Object retobj = meth.invoke(methobj, arglist);
               Integer retval = (Integer) retobj;
               System.out.println(retval.intvalue());
           } catch (Throwable e) {
               System.err.println(e);
           }
       }
    }

    假如一個(gè)程序在執(zhí)行的某處的時(shí)候才知道需要執(zhí)行某個(gè)方法,這個(gè)方法的名稱(chēng)是在程序的運(yùn)行過(guò)程中指定的 (例如,JavaBean 開(kāi)發(fā)環(huán)境中就會(huì)做這樣的事),那么上面的程序演示了如何做到。

    上例中,getMethod 用于查找一個(gè)具有兩個(gè)整型參數(shù)且名為 add 的方法。找到該方法并創(chuàng)建了相應(yīng)的 Method 對(duì)象之后,在正確的對(duì)象實(shí)例中執(zhí)行它。執(zhí)行該方法的時(shí)候,需要提供一個(gè)參數(shù)列表,這在上例中是分別包裝了整數(shù) 37 和 47 的兩個(gè) Integer 對(duì)象。執(zhí)行方法的返回的同樣是一個(gè) Integer 對(duì)象,它封裝了返回值 84。

    7.創(chuàng)建新的對(duì)象

    對(duì)于構(gòu)造器,則不能像執(zhí)行方法那樣進(jìn)行,因?yàn)閳?zhí)行一個(gè)構(gòu)造器就意味著創(chuàng)建了一個(gè)新的對(duì)象 (準(zhǔn)確的說(shuō),創(chuàng)建一個(gè)對(duì)象的過(guò)程包括分配內(nèi)存和構(gòu)造對(duì)象)。所以,與上例最相似的例子如下:

    import java.lang.reflect.*;

    public class constructor2 {
       public constructor2() {
       }

       public constructor2(int a, int b) {
           System.out.println("a = " + a + " b = " + b);
       }

       public static void main(String args[]) {
           try {
               Class cls = Class.forName("constructor2");
               Class partypes[] = new Class[2];
               partypes[0] = Integer.TYPE;
               partypes[1] = Integer.TYPE;
               Constructor ct = cls.getConstructor(partypes);
               Object arglist[] = new Object[2];
               arglist[0] = new Integer(37);
               arglist[1] = new Integer(47);
               Object retobj = ct.newInstance(arglist);
           } catch (Throwable e) {
               System.err.println(e);
           }
       }
    }

    根據(jù)指定的參數(shù)類(lèi)型找到相應(yīng)的構(gòu)造函數(shù)并執(zhí)行它,以創(chuàng)建一個(gè)新的對(duì)象實(shí)例。使用這種方法可以在程序運(yùn)行時(shí)動(dòng)態(tài)地創(chuàng)建對(duì)象,而不是在編譯的時(shí)候創(chuàng)建對(duì)象,這一點(diǎn)非常有價(jià)值。

    8.改變字段(域)的值

    reflection 的還有一個(gè)用處就是改變對(duì)象數(shù)據(jù)字段的值。reflection 可以從正在運(yùn)行的程序中根據(jù)名稱(chēng)找到對(duì)象的字段并改變它,下面的例子可以說(shuō)明這一點(diǎn):

    import java.lang.reflect.*;

    public class field2 {
       public double d;

       public static void main(String args[]) {
           try {
               Class cls = Class.forName("field2");
               Field fld = cls.getField("d");
               field2 f2obj = new field2();
               System.out.println("d = " + f2obj.d);
               fld.setDouble(f2obj, 12.34);
               System.out.println("d = " + f2obj.d);
           } catch (Throwable e) {
               System.err.println(e);
           }
       }
    }

    這個(gè)例子中,字段 d 的值被變?yōu)榱?12.34。

    9.使用數(shù)組

    本文介紹的 reflection 的最后一種用法是創(chuàng)建的操作數(shù)組。數(shù)組在 Java 語(yǔ)言中是一種特殊的類(lèi)類(lèi)型,一個(gè)數(shù)組的引用可以賦給 Object 引用。觀察下面的例子看看數(shù)組是怎么工作的:

    import java.lang.reflect.*;

    public class array1 {
       public static void main(String args[]) {
           try {
               Class cls = Class.forName("java.lang.String");
               Object arr = Array.newInstance(cls, 10);
               Array.set(arr, 5, "this is a test");
               String s = (String) Array.get(arr, 5);
               System.out.println(s);
           } catch (Throwable e) {
               System.err.println(e);
           }
       }
    }

    例中創(chuàng)建了 10 個(gè)單位長(zhǎng)度的 String 數(shù)組,為第 5 個(gè)位置的字符串賦了值,最后將這個(gè)字符串從數(shù)組中取得并打印了出來(lái)。

    下面這段代碼提供了一個(gè)更復(fù)雜的例子:

    import java.lang.reflect.*;

    public class array2 {
       public static void main(String args[]) {
           int dims[] = new int[]{5, 10, 15};
           Object arr = Array.newInstance(Integer.TYPE, dims);
           Object arrobj = Array.get(arr, 3);
           Class cls = arrobj.getClass().getComponentType();
           System.out.println(cls);
           arrobj = Array.get(arrobj, 5);
           Array.setInt(arrobj, 10, 37);
           int arrcast[][][] = (int[][][]) arr;
           System.out.println(arrcast[3][5][10]);
       }
    }
    例中創(chuàng)建了一個(gè) 5 x 10 x 15 的整型數(shù)組,并為處于 [3][5][10] 的元素賦了值為 37。注意,多維數(shù)組實(shí)際上就是數(shù)組的數(shù)組,例如,第一個(gè) Array.get 之后,arrobj 是一個(gè) 10 x 15 的數(shù)組。進(jìn)而取得其中的一個(gè)元素,即長(zhǎng)度為 15 的數(shù)組,并使用 Array.setInt 為它的第 10 個(gè)元素賦值。

    注意創(chuàng)建數(shù)組時(shí)的類(lèi)型是動(dòng)態(tài)的,在編譯時(shí)并不知道其類(lèi)型。

    posted on 2006-02-24 17:26 銀色幻想 閱讀(143) 評(píng)論(0)  編輯  收藏


    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲成a人片在线观看日本麻豆| 亚洲国产精品无码久久久| 亚洲欧美日韩中文二区| 最近中文字幕2019高清免费| 国产亚洲美女精品久久久久狼| 一级毛片大全免费播放| 久久精品国产精品亚洲下载 | 亚洲精品在线播放| 亚洲精品视频在线观看免费| 77777_亚洲午夜久久多人| **aaaaa毛片免费同男同女| 亚洲成av人片不卡无码| 久久99九九国产免费看小说| 亚洲一卡2卡3卡4卡5卡6卡| 午夜视频在线观看免费完整版| 亚洲精品无码不卡在线播放| 国产99视频精品免费视频7| 五月天国产成人AV免费观看| 亚洲女同成av人片在线观看| 国产日韩一区二区三免费高清| 亚洲精品自产拍在线观看动漫| 18女人毛片水真多免费| 亚洲一本一道一区二区三区| 亚洲Av无码国产情品久久| 在线人成免费视频69国产| 亚洲大香人伊一本线| 国产片免费在线观看| 国产在线观看无码免费视频| 97亚洲熟妇自偷自拍另类图片| 日韩毛片免费无码无毒视频观看| 亚洲av无码专区国产不乱码| 中文字幕无码精品亚洲资源网| 中文字幕免费视频| 亚洲av成人中文无码专区| 国产亚洲精久久久久久无码| 中国在线观看免费高清完整版| 三级片免费观看久久| 亚洲视频日韩视频| 亚洲Av无码乱码在线znlu| 最近免费中文字幕mv电影| 蜜桃传媒一区二区亚洲AV|