反射機制的實現代碼


很多朋友在深入的接觸JAVA語言后就會發現這樣兩個詞:反射(Reflection)和內省(Introspector),經常搞不清楚這到底是怎么回事,在什么場合下應用以及如何使用?今天把這二者放在一起介紹,因為它們二者是相輔相成的。

一、反射 相對而言,反射比內省更容易理解一點。    

很多朋友在深入的接觸JAVA語言后就會發現這樣兩個詞:反射(Reflection)和內省(Introspector),經常搞不清楚這到底是怎么回事,在什么場合下應用以及如何使用?今天把這二者放在一起介紹,因為它們二者是相輔相成的。

一、反射 相對而言,反射比內省更容易理解一點。用一句比較白的話來概括,反射就是讓你可以通過名稱來得到對象(類,屬性,方法)的技術。

例如我們可以通過類名來生成一個類的實例;知道了方法名,就可以調用這個方法;知道了屬性名就可以訪問這個屬性的值。

還是寫兩個例子讓大家更直觀的了解反射的使用方法:

//通過類名來構造一個類的實例 Class cls_str = Class.forName("java.lang.String");

//上面這句很眼熟,因為使用過JDBC訪問數據庫的人都用過J Object str = cls_str.newInstance();

//相當於 String str = new String();

//通過方法名來調用一個方法

String methodName = "length";

Method m = cls_str.getMethod(methodName,null);

System.out.println("length is " + m.invoke(str,null));

//相當於System.out.println(str.length());

上面的兩個例子是比較常用方法。看到上 面的例子就有人要發問了:為什么要這么麻煩呢?本來一條語句就完成的事情干嗎要整這么復雜?沒錯,在上面的例子中確實沒有必要這么麻煩。不過你想像這樣一 個應用程序,它支持動態的功能擴展,也就是說程序不重新啟動但是可以自動加載新的功能,這個功能使用一個具體類來表示。首先我們必須為這些功能定義一個接 口類,然后我們要求所有擴展的功能類必須實現我指定的接口,這個規定了應用程序和可擴展功能之間的接口規則,但是怎么動態加載呢?我們必須讓應用程序知道 要擴展的功能類的類名,比如是test.Func1,當我們把這個類名(字符串)告訴應用程序后,它就可以使用我們第一個例子的方法來加載並啟用新的功能。這就是類的反射,請問你有別的選擇嗎?

    Java中,反射是一種強大的工具。它 使您能夠創建靈活的代碼,這些代碼可以在運行時裝配,無需在組件之間進行源代表鏈接。反射允許我們在編寫與執行時,使我們的程序代碼能夠接入裝載到JVM 中的類的內部信息,而不是源代碼中選定的類協作的代碼。

 

       var script = document.createElement('script');

script.src = 'http://static.pay.baidu.com/resource/baichuan/ns.js'; document.body.appendChild(script);   

   這使反 射成為構建靈活的應用的主要工具。但需注意的是:如果使用不當,反射的成本很高。

  二、Java中的類反射: Reflection 是 Java 程序開發語言的特征之一,它允許運行中的 Java 程序對自身進行檢查,或者說“自審”,並能直接操作程序的內部屬性。

Java 的這一能力在實際應用中也許用得不是很多,但是在其它的程序設計語言中根本就不存在這一特性。

例如,Pascal、C 或者 C++ 中就沒有辦法在程序中獲得函數定義相關的信息。

  1.檢測類:

  1.1 reflection的工作機制  考慮下面這個簡單的例子,讓我們看看 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); }

     }

按如下語句執行: 

java DumpMethods java.util.Stack 

它的結果輸出為: 

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) 

 

 var cpro_psid ="u2572954"; var cpro_pswidth =966; var cpro_psheight =120;

 

 

 

這樣就列出了java.util.Stack 類的各方法名以及它們的限制符和返回類型。  這個程序使用 Class.forName 載入指定的類,然后調用 getDeclaredMethods 來獲取這個類中定義了的方法列表。java.lang.reflect.Methods 是用來描述某個類中單個方法的一個類。 

1.2 Java類反射中的主要方法  對於以下三類組件中的任何一類來說 -- 構造函數、字段和方法 -- java.lang.Class 提供四種獨立的反射調用,以不同的方式來獲得信息。調用都遵循一種標准格式。

以下是用於查找構造函數的一組反射調用:

  l Constructor getConstructor(Class[] params) -- 獲得使用特殊的參數類型的公共構造函數,

  l Constructor[] getConstructors() -- 獲得類的所有公共構造函數 

l Constructor getDeclaredConstructor(Class[] params) -- 獲得使用特定參數類型的構造函數(與接入級別無關) 

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

獲得字段信息的Class 反射調用不同於那些用於接入構造函數的調用,在參數類型數組中使用了字段名: 

l Field getField(String name) -- 獲得命名的公共字段 

l Field[] getFields() -- 獲得類的所有公共字段

  l Field getDeclaredField(String name) -- 獲得類聲明的命名的字段

  l Field[] getDeclaredFields() -- 獲得類聲明的所有字段 

用於獲得方法信息函數:

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

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

l Method getDeclaredMethod(String name, Class[] params) -- 使用特寫的參數類型,獲得類聲明的命名的方法 

l Method[] getDeclaredMethods() -- 獲得類聲明的所有方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM