1. 程式人生 > >且談談我對Java反射的理解

且談談我對Java反射的理解

 在張老師的課程當中,談到了反射的概念,用馮偉立學長的最簡單的一句話來說就是:反射就是把Java類中的各種成分對映成相應的Java類。

當然在很多教科書上有其他的一些定義,大多數比較長的解釋。比如說:

JAVA反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為java語言的反射機制。 JAVA反射(放射)機制:“程式執行時,允許改變程式結構或變數型別,這種語言稱為動態語言”。從這個觀點看,Perl,Python,Ruby是動態語言,C++,Java,C#不是動態語言。但是JAVA有著一個非常突出的動態相關機制:Reflection,用在Java身上指的是我們可以於執行時載入、探知、使用編譯期間完全未知的classes。換句話說,Java程式可以載入一個執行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並生成其物件實體、或對其fields設值、或喚起其methods。 Java反射機制主要提供了以下功能: 在執行時判斷任意一個物件所屬的類;在執行時構造任意一個類的物件;在執行時判斷任意一個類所具有的成員變數
和方法;在執行時呼叫任意一個物件的方法;生成動態代理。
利用反射機制能獲得什麼資訊
         一句話,類中有什麼資訊,它就可以獲得什麼資訊,不過前提是得知道類的名字,要不就沒有後文了
    首先得根據傳入的類的全名來建立Class物件。
    Class c=Class.forName("className");註明:className必須為全名,也就是得包含包名,比如,cn.netjava.pojo.UserInfo;
    Object obj=c.newInstance();//建立物件的例項
    OK,有了物件就什麼都好辦了,想要什麼資訊就有什麼資訊了。  
    獲得建構函式的方法
    Constructor getConstructor(Class[] params)//根據指定引數獲得public構造器

    Constructor[] getConstructors()//獲得public的所有構造器

    Constructor getDeclaredConstructor(Class[] params)//根據指定引數獲得public和非public的構造器

    Constructor[] getDeclaredConstructors()//獲得public的所有構造器
   
    獲得類方法的方法
    Method getMethod(String name, Class[] params),根據方法名,引數型別獲得方法

    Method[] getMethods()//獲得所有的public方法

    Method getDeclaredMethod(String name, Class[] params)//根據方法名和引數型別,獲得public和非public的方法

    Method[] getDeclaredMethods()//獲得所以的public和非public方法
   
    獲得類中屬性的方法
    Field getField(String name)//根據變數名得到相應的public變數

    Field[] getFields()//獲得類中所以public的方法

    Field getDeclaredField(String name)//根據方法名獲得public和非public變數

    Field[] getDeclaredFields()//獲得類中所有的public和非public方法


Java的反射非常強大,傳遞class, 可以動態的生成該類、取得這個類的所有資訊,包括裡面的屬性、方法以及建構函式等,甚至可以取得其父類或父接口裡面的內容。

  obj.getClass().getDeclaredMethods();//取得obj類中自己定義的方法, 包括私有的方法。   obj.getClass().getMethods();//取得obj類中自己定義的方法及繼承過來的方法, 但私有方法得不到。   同樣, 對field也是一樣,obj.getClass().getDeclaredFields();取得的是這個類中所有的屬性,包括私有的field; 對obj.getClass().getFields();//取得是自己以及接繼承來的屬性, 但不能取得自己的私有屬性。
Java程式碼  收藏程式碼
  1. static Object create(Class clazz) throws Exception {  
  2.     Constructor con = clazz.getConstructor(String.class);  
  3.     Object obj = con.newInstance("test name");  
  4.     return obj;  
  5.   }  
  6.   static void invoke1(Object obj, String methodName)  
  7.       throws IllegalArgumentException, IllegalAccessException,  
  8.       InvocationTargetException, Exception, NoSuchMethodException {  
  9.     Method[] ms = obj.getClass().getDeclaredMethods();  
  10.     ms = obj.getClass().getMethods();  
  11.     for (Method m : ms) {  
  12.       // System.out.println(m.getName());  
  13.       if (methodName.equals(m.getName()))  
  14.         m.invoke(obj, null);  
  15.     }  
  16.     Method m = obj.getClass().getMethod(methodName, null);  
  17.     m.invoke(obj, null);  
  18.   }  
  19.   static void field(Class clazz) throws Exception {  
  20.     Field[] fs = clazz.getDeclaredFields();  
  21.     //fs = clazz.getFields();  
  22.     for (Field f : fs)  
  23.       System.out.println(f.getName());  
  24.   }  
  25.   static void annon(Class clazz) throws Exception {  
  26.     Annotation[] as = clazz.getAnnotations();  
  27.   }  
反射在Java中對初學者來說算是比較難理解的一塊了。 對於一個程式設計師來說,面向物件程式設計往往是一個分水嶺,有很多程式設計師理解不了面向物件的機制,往往就放棄了繼續前進。 我是做php程式設計出身,php支援面向過程,也支援面向物件程式設計,面向物件程式設計往往也是php程式設計師的分水嶺。 Javaweb中,自定義標籤是一個程式設計師的分水嶺。而Java的反射,我認為也是一個程式設計師實力衡量的一個很重要的標準,雖然反射在一定程度上增加執行程式的成本,但是可以簡化很多工作。