1. 程式人生 > >java反射機制的實現原理 (一)

java反射機制的實現原理 (一)

反射機制:所謂的反射機制就是java語言在執行時擁有一項自觀的能力。通過這種能力可以徹底的瞭解自身的情況為下一步的動作做準備。下面具體介紹一下java的反射機制。這裡你將顛覆原來對java的理解。
Java的反射機制的實現要藉助於4個類:class,Constructor,Field,Method;其中class代表的時類對 象,Constructor-類的構造器物件,Field-類的屬性物件,Method-類的方法物件。通過這四個物件我們可以粗略的看到一個類的各個組 成部分。

Class:程式執行時,java執行時系統會對所有的物件進行執行時型別的處理。這項資訊記錄了每個物件所屬的類,虛擬機器通常使用執行時型別資訊選擇正 確的方法來執行(摘自:白皮書)。但是這些資訊我們怎麼得到啊,就要藉助於class類物件了啊。在Object類中定義了getClass()方法。我 們可以通過這個方法獲得指定物件的類物件。然後我們通過分析這個物件就可以得到我們要的資訊了。

比如:ArrayList arrayList;

Class clazz = arrayList.getClass();

然後我來處理這個物件clazz。

當然了Class類具有很多的方法,這裡重點將和Constructor,Field,Method類有關係的方法。

Reflection 是 Java 程式開發語言的特徵之一,它允許執行中的 Java 程式對自身進行檢查,或者說“自審”,並能直接操作程式的內部屬性。Java 的這一能力在實際應用中也許用得不是很多,但是個人認為要想對java有個更加深入的瞭解還是應該掌握的。

1.檢測類:

reflection的工作機制

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

按如下語句執行:

java DumpMethods java.util.ArrayList

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

Java類反射中的主要方法

對於以下三類元件中的任何一類來說 -- 建構函式、欄位和方法 -- java.lang.Class 提供四種獨立的反射呼叫,以不同的方式來獲得資訊。呼叫都遵循一種標準格式。以下是用於查詢建構函式的一組反射呼叫:

Constructor getConstructor(Class[] params) -- 獲得使用特殊的引數型別的公共建構函式,

Constructor[] getConstructors() -- 獲得類的所有公共建構函式

Constructor getDeclaredConstructor(Class[] params) -- 獲得使用特定引數型別的建構函式(與接入級別無關)

Constructor[] getDeclaredConstructors() -- 獲得類的所有建構函式(與接入級別無關)

獲得欄位資訊的Class 反射呼叫不同於那些用於接入建構函式的呼叫,在引數型別陣列中使用了欄位名:

Field getField(String name) -- 獲得命名的公共欄位

Field[] getFields() -- 獲得類的所有公共欄位

Field getDeclaredField(String name) -- 獲得類宣告的命名的欄位

Field[] getDeclaredFields() -- 獲得類宣告的所有欄位

用於獲得方法資訊函式:

Method getMethod(String name, Class[] params) -- 使用特定的引數型別,獲得命名的公共方法

Method[] getMethods() -- 獲得類的所有公共方法

Method getDeclaredMethod(String name, Class[] params) -- 使用特寫的引數型別,獲得類宣告的命名的方法

Method[] getDeclaredMethods() -- 獲得類宣告的所有方法

使用 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;

它們可獲得基本型別的類資訊。其中後一種方法中訪問的是基本型別的封裝類 (如 Intege ) 中預先定義好的 TYPE 欄位。

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

一旦取得這個資訊,就可以進行第三步了——使用 reflection API 來操作這些資訊,如下面這段程式碼:

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

Method m[] = c.getDeclaredMethods();

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

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

處理物件:

a.建立一個Class物件

b.通過getField 建立一個Field物件

c.呼叫Field.getXXX(Object)方法(XXX是Int,Float等,如果是物件就省略;Object是指例項).

例如