Java中的反射機制

---------------------- android培訓java培訓、期待與您交流! ----------------------

 

Java中的反射機制

 

     反射是Java程序開發語言的特徵之一。它允許動態地發現和綁定類、方法、字段,以及所有其他的由語言所產生的元素。反射可以做的不僅僅是簡單地列舉類、字段以及方法。通過反射,還能夠在需要時完成創建實例、調用方法以及訪問字段的工作。反射是Java被視爲動態(或準動態)語言的關鍵。

歸納起來,Java反射機制主要提供了一下功能:

在運行時判斷任意一個對象所屬的類。

在運行時構造任意一個類的對象。

在運行時判斷任意一個類所具有的成員變量和方法。

在運行時調用任意一個對象的方法。通過反射甚至可以調用到private的方法。

生成動態代理。

Java反射API

    Java反射所需的類並不多,主要有java.lang.Class類和java.lang.reflect包中的FieldConstructorMethodArray類,下面對這些類做一個簡單的說明。

Class類:Class類的實例表示正在運行的 Java 應用程序中的類和接口。

Field類:Field 提供有關類或接口的單個字段的信息,以及對它的動態訪問權限。反射的字段可能是一個類(靜態)字段或實例字段。 簡單的理解可以把它看成一個封裝反射類的屬性的類。

ConstructorConstructor 提供關於類的單個構造方法的信息以及對它的訪問權限。Constructor類封裝了反射類的構造方法。

Method類:Method提供關於類或接口上單獨某個方法(以及如何訪問該方法)的信息。所反映的方法可能是類方法或實例方法(包括抽象方法)。它是用來封裝反射類方法的一個類。

 

       其中,Class類是Java反射的起源,針對任何一個你想探勘的類,只有先爲它產生一個Class類的對象,接下來才能通過Class對象獲取其他想要的信息。

Java程序在運行時,系統會對所有的對象進行所謂的運行時類型標識,用來保存這些類型信息的類就是Class類。Class類封裝一個對象和接口運行時的狀態。

JVM爲每種類型管理着一個對一無二的Class對象。也就是說,每個類(型)都有一個Class對象。Java程序運行過程中,當需要創建某個類的實例時,JVM首先檢查所要加載的類對應的Class對象是否存在。如果還不存在,JVM就會根據類名查找對應的字節碼文件並加載,接着創建對應的Class對象,最後才創建出這個類的實例。

也就是說,運行中的類或者接口在JVM中都會有一個對應的Class對象存在,它保存了對應類和接口的類型信息。要想獲取類和接口的相應信息,需要先獲取這個Class對象。

一.獲取字節碼文件對象(Class對象)。

三種方式

       1getClass()方法。調用Object類的getClass()方法來得到Class對象。

              特點:必須要明確具體的類,而且要通過該類創建對象。用對象的方法纔可以獲取。public final Class<?>getClass(); 此方法爲Object類中方法。

         public class ReflectDemo1{

public staticvoid getClassObject_1(){

                   Personp  = new Person();        //1,創建Person對象

                   Classclazz = p.getClass();          //2,獲取字節碼對象。getClass();

                   Personp2 = new Person();

                   Classclazz2 = p2.getClass();

                   System.out.println(clazz==clazz2);    //返回true

           }

         }       

        

2,通過類型的class靜態屬性獲取其對應的Class對象

每一個數據類型都有一個靜態的屬性class,每一個類型都對應自己的Class類型的對象。

       特點:雖然不用在創建對象了,但是還是要先明確該類,在調用其靜態的屬性完成。

          public class ReflectDemo2{

              publicstaticvoid getClassObject_2() {

                    Class clazz = Person.class;

                   //Class clazz = int.class;

           }

}

3,使用的是Class類中的forName方法。根據指定的類名來獲取其字節碼文件對象。

               特點:只需要一個類名字符串即可。forName方法自動會根據指定的字符串名稱去查找對應的類文件。如果找到就將其加載進內存,並封裝成Class對象。

如果沒有找到拋出ClassNotFoundException              

               * 因爲只需要字符串名稱所以擴展性很強。

               * 以這種方式爲主提高程序的擴展性

              public class ReflectDemo2{

                publicstaticvoid getClassObject_3() throws Exception {

                      String className = "cn.itcast.bean.Person";

                      Class clazz = Class.forName(className);

                      System.out.println(clazz);

                   }

}

二.通過字節碼文件創建對象

1.使用類中空參構造函數進行初始化對象。

 通過字節碼文件對象的newInstance方法完成該類實例的創建。

                        Class clazz =Class.forName("cn.itcast.bean.Person");

                        Object obj = clazz.newInstance();//該方法使用的就是該類中的空參數構造函數進行初始化對象。

2. 通過有參數的構造函數進行實例化

既然要根據指定的構造函數進行初始化,就必須要先獲取要用於初始化的構造函數,再通過該構造函數進行對象創建的初始化。

           publicstaticvoid createObject_2() throws Exception{

                   Classclazz = Class.forName("cn.itcast.bean.Person");

                   Constructorconstructor = clazz.getConstructor(String.class,int.class);     //獲取指定參數的構造函數。當然是Class對象完成。

                 Objectobj = constructor.newInstance("zhangsan",28);    //通過該構造函數進行對象的創建並初始化。並傳遞指定的實際參數。

                   }

三.通過反射獲取類中字段

publicstaticvoidgetFieldDemo() throwsException{

                   StringclassName = "cn.itcast.bean.Person";

                   Classclazz = Class.forName(className);

                   Objectobj = clazz.newInstance();

                   //獲取該類中的名稱爲agePrivate修飾)的字段。

                   //Field field = clazz.getField("age");//該方法只能獲取公有的字段。

//獲取私有字段必須使用getDeclaredField();

                   Fieldfield = clazz.getDeclaredField("age");

                   //調用取消對成員的訪問控制檢查的能力的方法。

                   field.setAccessible(true);//暴力訪問。

//System.out.println(field);

                   field.set(obj,38);

                   Objectvalue = field.get(obj);//因爲age私有,會出現IllegalAccessException:

                   System.out.println("value="+value);

         }

 

四.通過反射獲取類中方法

      Class類中的方法:

public Method getMethod(Stringname, Class<?>...parameterTypes):返回一個Method對象,它反映此Class對象所表示的類或接口的指定公共成員方法。name參數是一個String,用於指定所需方法的簡稱。parameterTypes參數是按聲明順序標識該方法形參類型的Class對象的一個數組。如果parameterTypesnull,則按空數組處理。

public Method getDeclaredMethod(String name, Class<?>... parameterTypes): 返回一個 Method 對象,該對象反映此 Class 對象所表示的類或接口的指定已聲明方法。
       Method類中的方法:
          public Object invoke(Object obj, Object... args):對帶有指定參數的指定對象調用由此 Method 對象表示的底層方法。
                     
                         

publicstaticvoid getSingleMethodDemo() throws Exception {

                   StringclassName = "cn.itcast.bean.Person";

                   Classclazz = Class.forName(className);

                   Objectobj = clazz.newInstance();

                   //獲取一個空參數的公有權限方法。pubMethod

                   Method method =clazz.getMethod("pubMethod", null);              

                   //方法怎麼運行,方法對象自己最清楚。

                   method.invoke(obj, null);

                  

                   //獲取有參數的public方法。parMethod.

                   Method method = clazz.getMethod("parMethod",String.class,int.class);           

                   method.invoke(obj,"xiaoming",47);

                  

                   //獲取私有方法。

                   Method method =clazz.getDeclaredMethod("priMethod", null);

                   method.setAccessible(true);

                   method.invoke(obj, null);

                  

                   //獲取靜態的方法。

                   Methodmethod = clazz.getMethod("staMethod", null);

                   method.invoke(null, null);    //靜態方法不需要創建對象來調用。後一個null爲空參

                  

         }

         /*

          * 獲取所有方法。

          */

         publicstaticvoidgetMethodDemo() throwsException {

                  

                   StringclassName = "cn.itcast.bean.Person";

                   Classclazz = Class.forName(className);

                   Objectobj = clazz.newInstance();

                  

                   //獲取所有方法。

                   Method[]methods = clazz.getMethods();

                  

                   methods= clazz.getDeclaredMethods();

                   for(Method method : methods){

                            System.out.println(method);

                   }

                  

                  

         }

---------------------- android培訓java培訓、期待與您交流! ----------------------詳細請查看:http://edu.csdn.net/heima
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章