亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

JAVA反射機制實例教程

2019-11-26 15:25:15
字體:
來源:轉載
供稿:網友

本文以實例形式詳細講述了Java的反射機制,是Java程序設計中重要的技巧。分享給大家供大家參考。具體分析如下:

首先,Reflection是Java 程序開發語言的特征之一,它允許運行中的 Java 程序對自身進行檢查,或者說"自審",并能直接操作程序的內部屬性。例如,使用它能獲得 Java 類中各成員的名稱并顯示出來。 Java 的這一能力在實際應用中也許用得不是很多,但是在其它的程序設計語言中根本就不存在這一特性。例如,Pascal、C 或者 C++ 中就沒有辦法在程序中獲得函數定義相關的信息。

JavaBean 是 reflection 的實際應用之一,它能讓一些工具可視化的操作軟件組件。這些工具通過 reflection 動態的載入并取得 Java 組件(類) 的屬性。

1. 一個簡單的例子

考慮下面這個簡單的例子,讓我們看看 reflection 是如何工作的。

import java.lang.reflect.*; public class DumpMethods {   public static void main(String args[]) {    try {       Class c = Class.forName("java.util.Stack");       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);    }   } }

它的結果輸出為:

public synchronized java.lang.Object java.util.Stack.pop()public java.lang.Object java.util.Stack.push(java.lang.Object)public boolean java.util.Stack.empty()public synchronized java.lang.Object java.util.Stack.peek()public synchronized int java.util.Stack.search(java.lang.Object)

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

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

2.開始使用 Reflection

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

下面就是獲得一個 Class 對象的方法之一:

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

這條語句得到一個 String 類的類對象。還有另一種方法,如下面的語句:

Class c = int.class; 或者 Class c = Integer.TYPE;

它們可獲得基本類型的類信息。其中后一種方法中訪問的是基本類型的封裝類 (如 Integer) 中預先定義好的 TYPE 字段。

第二步是調用諸如 getDeclaredMethods 的方法,以取得該類中定義的所有方法的列表。

一旦取得這個信息,就可以進行第三步了――使用 reflection API 來操作這些信息,如下面這段代碼:

Class c = Class.forName("java.lang.String"); Method m[] = c.getDeclaredMethods(); System.out.println(m[0].toString()); 

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

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

模擬 instanceof 操作符

得到類信息之后,通常下一個步驟就是解決關于 Class 對象的一些基本的問題。例如,Class.isInstance 方法可以用于模擬 instanceof 操作符:

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

在這個例子中創建了一個S 類的 Class 對象,然后檢查一些對象是否是S的實例。Integer(37) 不是,但 new S()是。

3.找出類的方法

找出一個類中定義了些什么方法,這是一個非常有價值也非常基礎的 reflection 用法。下面的代碼就實現了這一用法:

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);     }   } }

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

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

輸出的結果如下:

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.獲取構造器信息

獲取類構造器的用法與上述獲取方法的用法類似,如:

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);    }   } }

這個例子中沒能獲得返回類型的相關信息,那是因為構造器沒有返回類型。

這個程序運行的結果是:

name = Constructor1decl class = class Constructor1param #0 intparam #1 double-----name = Constructor1decl class = class Constructor1-----

5.獲取類的字段(域)

找出一個類中定義了哪些數據字段也是可能的,下面的代碼就在干這個事情:

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);    }   } }

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

name = ddecl class = class Field1type = doublemodifiers = private-----name = idecl class = class Field1type = intmodifiers = public static final-----name = sdecl class = class Field1type = class java.lang.Stringmodifiers = -----

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

6.根據方法的名稱來執行方法

文本到這里,所舉的例子無一例外都與如何獲取類的信息有關。我們也可以用 reflection 來做一些其它的事情,比如執行一個指定了名稱的方法。下面的示例演示了這一操作:

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);    }   } }

假如一個程序在執行的某處的時候才知道需要執行某個方法,這個方法的名稱是在程序的運行過程中指定的 (例如,JavaBean 開發環境中就會做這樣的事),那么上面的程序演示了如何做到。

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

7.創建新的對象

對于構造器,則不能像執行方法那樣進行,因為執行一個構造器就意味著創建了一個新的對象 (準確的說,創建一個對象的過程包括分配內存和構造對象)。所以,與上例最相似的例子如下:

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);    }   } }

根據指定的參數類型找到相應的構造函數并執行它,以創建一個新的對象實例。使用這種方法可以在程序運行時動態地創建對象,而不是在編譯的時候創建對象,這一點非常有價值。

8.改變字段(域)的值

reflection 的還有一個用處就是改變對象數據字段的值。reflection 可以從正在運行的程序中根據名稱找到對象的字段并改變它,下面的例子可以說明這一點:

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);    }   } }

這個例子中,字段 d 的值被變為了 12.34。

9.使用數組

本文介紹的 reflection 的最后一種用法是創建的操作數組。數組在 Java 語言中是一種特殊的類類型,一個數組的引用可以賦給 Object 引用。觀察下面的例子看看數組是怎么工作的:

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);    }   } }

例中創建了 10 個單位長度的 String 數組,為第 5 個位置的字符串賦了值,最后將這個字符串從數組中取得并打印了出來。

下面這段代碼提供了一個更復雜的例子:

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]);   } }

例中創建了一個 5 x 10 x 15 的整型數組,并為處于 [3][5][10] 的元素賦了值為 37。注意,多維數組實際上就是數組的數組,例如,第一個 Array.get 之后,arrobj 是一個 10 x 15 的數組。進而取得其中的一個元素,即長度為 15 的數組,并使用 Array.setInt 為它的第 10 個元素賦值。

注意創建數組時的類型是動態的,在編譯時并不知道其類型。

相信本文所述對大家Java程序設計的學習有一定的借鑒價值。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日本高清视频| 久久天天躁日日躁| 久久97久久97精品免视看| 日韩精品中文字幕在线| 国产成人精品优优av| 日韩免费观看在线观看| 欧美性生交大片免费| 欧美黑人巨大xxx极品| 韩国视频理论视频久久| 最近2019免费中文字幕视频三| 粗暴蹂躏中文一区二区三区| 欧美亚洲另类激情另类| 一本色道久久88综合日韩精品| 91精品在线播放| 中文字幕亚洲图片| 日韩av中文字幕在线免费观看| 最新日韩中文字幕| 亚洲欧美在线免费| 国产精品wwwwww| 欧美日韩亚洲一区二区| 亚洲午夜久久久久久久| 欧美专区国产专区| wwwwwwww亚洲| 久久成人人人人精品欧| 亚洲黄色av网站| 亚洲xxx大片| 国产中文字幕91| 亚洲精品美女久久久| 欧美日韩国产在线播放| 国产不卡av在线免费观看| 国产精品xxxxx| 九九热这里只有精品免费看| 中文字幕精品视频| 国产欧美日韩91| 国产精品一区二区电影| 成人观看高清在线观看免费| 亚洲成人黄色在线观看| 91久久精品久久国产性色也91| 成人写真视频福利网| 国产热re99久久6国产精品| 久久99热这里只有精品国产| 欧美激情国产高清| 日韩精品福利网站| 在线日韩欧美视频| 伊人av综合网| 日韩毛片在线看| 在线观看国产精品淫| 欧美日韩国产精品一区二区三区四区| 亚洲综合中文字幕68页| 日韩精品有码在线观看| 精品久久久一区| 亚洲色图校园春色| 精品国模在线视频| 国产三级精品网站| 国内外成人免费激情在线视频网站| 国内精品400部情侣激情| 精品性高朝久久久久久久| 欧美日韩xxx| 亚洲精品久久久久久久久久久久久| 国产丝袜一区视频在线观看| 91精品国产自产在线老师啪| 亚洲深夜福利视频| 久久天天躁狠狠躁夜夜爽蜜月| 亚洲一级黄色片| 久久精品国产综合| 亚洲免费视频观看| 亚洲成人久久网| 午夜免费在线观看精品视频| 8050国产精品久久久久久| 日韩中文字幕在线看| 精品亚洲精品福利线在观看| 中文字幕av一区中文字幕天堂| 91久久久久久久久| 国产mv久久久| 韩国v欧美v日本v亚洲| 一区二区欧美在线| 人人做人人澡人人爽欧美| 日韩欧美成人精品| 精品丝袜一区二区三区| 成人福利免费观看| 亚洲天堂免费观看| 国产精品视频网站| 国产精品大陆在线观看| 成人精品在线观看| 国产成人精品a视频一区www| 欧美综合在线观看| 欧美激情综合色综合啪啪五月| 国产在线播放91| 久久精品视频在线播放| 8050国产精品久久久久久| 国产一区二区三区欧美| 中文字幕欧美精品日韩中文字幕| 精品国产欧美一区二区三区成人| 欧美大片欧美激情性色a∨久久| 成人免费视频xnxx.com| 亚洲va男人天堂| 亚洲最大的成人网| 精品自拍视频在线观看| 欧美精品免费在线观看| 亚洲美女久久久| 一本色道久久88综合亚洲精品ⅰ| 亚洲a∨日韩av高清在线观看| 欧美天堂在线观看| 国产精品91视频| 中文字幕欧美日韩va免费视频| 日韩av观看网址| 久久精品国产精品亚洲| 亚洲jizzjizz日本少妇| 国产精品成人av在线| 亚洲 日韩 国产第一| 在线精品91av| 91精品国产91久久久久久最新| 欧美交受高潮1| 亚洲成人av在线| 亚洲欧洲一区二区三区在线观看| 国产精品99导航| 国产成人一区二区在线| 精品综合久久久久久97| 成人性生交大片免费看小说| 国产精品丝袜视频| 精品久久久久久久久久| 国产精品流白浆视频| 日本道色综合久久影院| 国产日韩欧美日韩| 日韩av一区在线| 91色在线视频| 亚洲成年人在线播放| 亚洲精品456在线播放狼人| 69av在线播放| 亚洲精品美女久久| 91美女片黄在线观| 深夜精品寂寞黄网站在线观看| 久久天天躁狠狠躁老女人| 国产亚洲成精品久久| 97国产精品视频| 精品国产欧美成人夜夜嗨| 一夜七次郎国产精品亚洲| 这里只有精品视频| 成人激情视频小说免费下载| 久久久亚洲影院| 在线成人激情黄色| 亚洲精品一区二区三区不| 一区二区国产精品视频| 久久免费视频在线观看| 日韩www在线| 91在线视频精品| 91亚洲精品在线观看| 久久精品国产一区二区三区| 国产婷婷97碰碰久久人人蜜臀| 欧美疯狂xxxx大交乱88av| 欧美大片免费观看在线观看网站推荐| 国产精品专区第二| 最近2019中文字幕一页二页| 国产精品爱啪在线线免费观看| 欧美性xxxx18| 国产精品久久久久久久久久小说| 欧美激情视频一区二区| 亚洲日韩欧美视频| 久久久久国产精品免费| 欧美激情中文网| 91国产精品视频在线| 欧美精品国产精品日韩精品| 亚洲欧美精品一区| 亚洲国产天堂网精品网站|