java中反射機制的學習

一、反射的理解

首先我們看看網友們對於反射的理解.

A:                                                                                                                                                          正常情況是java虛擬機根據你的類的定義,創建出一個對象。反射則是相反的過程,可以根據一個對象的引用,解析它的定義信息(屬性,方法),進而可以操作它的屬性,調   用它的方法,當然也可以創建出新的對象。---來自qwqwqw408
B:                                                                                                                                                          一句話來概括反射機制就是:動態地獲取類的一切信息,並利用這些信息做一些你想做的事情---來自justinavril
第一 反射可以操作某個類的私有變量和方法
第二 反射操作對象更加靈活 如 struts的form  只要有了form對象和 property名字就可以利用反射給property賦值和取值 對這類操作 一個方法就可以搞定。---來自<span style="color: rgb(102, 102, 102); font-family: Helvetica, Tahoma, Arial, sans-serif;  line-height: 24px; background-color: rgb(245, 245, 245);"><strong>justinavril</strong></span>
C:                                                                                                                                                          如果hibernate不用字段進行反射映射 那麼每個HQL的編譯和結果處理 將無法進行。
第三 反射方式調用方法 動態代理 擴展API 。sping ioc,aop也都是用的反射
第四  運行過程中對未知類進行初始化等
我都是用反射在竊取和擴展一些收費的無法反編譯的API---來自a276202460

沒有錯,他們說的都對就是對類的動態加載,你可以通過反射來操縱類中的一切,無論這個類中的變量和方法是不是private,我們都可以應用。

二、反射機制中需要使用到的類

我把需要使用的類列在下表中,其中對我們特別有用的類,通過着重標記顯示出來,並將在後面的使用中逐步解釋:

三、Class

  首先向大家說明一點,Class本身就是一個類,Class是該類的名稱。看以下下面這個類的定義:

  public class MyButton extends Button {...}

   注意到上面的class的首字母是小寫,它表示的是一種類類型,但是我們的Class是一個類,相當於上面定義的MyButton類。所以,千萬不要把這裏的Class做爲一個類類型來理解。明白這一點,我們繼續。

  Class類是整個Java反射機制的源頭,Class類本身表示Java對象的類型,我們可通過一個Object對象的getClass()方法取得一個對象的類型,此函數返回的就是一個Class類。獲取Class對象的方法有很多種:

boolean.class byte.class  int.class  long.class float.class double.class 

  在平時的使用,要注意對這幾種方法的靈活運用,尤其是對Class.forName()方法的使用。因爲在很多開發中,會直接通過類的名稱取得Class類的對象。

四、獲取類的相關信息

1、獲取構造方法

  Class類提供了四個public方法,用於獲取某個類的構造方法。

    Constructor getConstructor(Class[] params)     根據構造函數的參數,返回一個具體的具有public屬性的構造函數

    Constructor getConstructors()     返回所有具有public屬性的構造函數數組

    Constructor getDeclaredConstructor(Class[] params)     根據構造函數的參數,返回一個具體的構造函數(不分public和非public屬性)

    Constructor getDeclaredConstructors()    返回該類中所有的構造函數數組(不分public和非public屬性)

  由於Java語言是一種面向對象的語言,具有多態的性質,那麼我們可以通過構造方法的參數列表的不同,來調用不同的構造方法去創建類的實例。同樣,獲取不同的構造方法的信息,也需要提供與之對應的參數類型信息;因此,就產生了以上四種不同的獲取構造方法的方式。

2、獲取類的成員方法

  與獲取構造方法的方式相同,存在四種獲取成員方法的方式。

    Method getMethod(String name, Class[] params)    根據方法名和參數,返回一個具體的具有public屬性的方法

    Method[] getMethods()    返回所有具有public屬性的方法數組

    Method getDeclaredMethod(String name, Class[] params)    根據方法名和參數,返回一個具體的方法(不分public和非public屬性)

    Method[] getDeclaredMethods()    返回該類中的所有的方法數組(不分public和非public屬性)

     在獲取類的成員方法時,有一個地方值得大家注意,就是getMethods()方法和getDeclaredMethods()方法。

    getMethods():用於獲取類的所有的public修飾域的成員方法,包括從父類繼承的public方法和實現接口的public方法;

    getDeclaredMethods():用於獲取在當前類中定義的所有的成員方法和實現的接口方法,不包括從父類繼承的方法。

3、獲取類的成員變量(成員屬性)

  存在四種獲取成員屬性的方法

    Field getField(String name)    根據變量名,返回一個具體的具有public屬性的成員變量

    Field[] getFields()    返回具有public屬性的成員變量的數組

    Field getDeclaredField(String name)    根據變量名,返回一個成員變量(不分public和非public屬性)

    Field[] getDelcaredField()    返回所有成員變量組成的數組(不分public和非public屬性)

4、獲取類、屬性、方法的修飾域

  類ClassMethodConstructorField都有一個public方法int getModifiers()。該方法返回一個int類型的數,表示被修飾對象( Class、 Method、 Constructor、 Field )的修飾類型的組合值。

  在開發文檔中,可以查閱到,Modifier類中定義了若干特定的修飾域,每個修飾域都是一個固定的int數值,列表如下:

    

五、如何調用類中的private方法

  

1、創建一個類的實例

  在得到一個類的Class對象之後,我們可以利用類Constructor去實例化該對象。Constructor支持泛型,也就是它本身應該是Constructor<T>

    

                       //獲得無參數的構造函數
			Constructor constructor = animalClass03.getConstructor(null);
			//通過獲得的無參數構造器可以 通過newInstance來實現一個對象;
			Object monkey01 = constructor.newInstance();

2、行爲

  Method類中包含着類的成員方法的信息。在Method類中有一個public成員函數:Object invoke(Object receiver, Object... args),參數receiver指明瞭調用對象,參數args指明瞭該方法所需要接收的參數。由於我們是在運行時動態的調用類的方法,無法提前知道該類的參數類型和返回值類型,所以傳入的參數的類型是Object,返回的類型也是Object。(因爲Object類是所有其他類的父類)

  

/**獲得類的方法並調用方法**///其實和變量沒有太大的區別,區別是增加了參數而已
			Method[] methods = animalClass03.getDeclaredMethods();
			for(int i=0;i<methods.length;i++){
				if(methods[i].getName().equals("yaoWeiba")){
					methods[i].setAccessible(true);
					Object[] parameters = new Object[]{
							new String("小強"),true,3
					};
					methods[i].invoke(monkey03, parameters);
				}
			}

 3、屬性

  對類的成員變量進行讀寫,在Field類中有兩個public方法:

    Object get(Object object),該方法可用於獲取某成員變量的值

    Void set(Object object, Object value),該方法設置某成員變量的值

  其中,Object參數是需要傳入的對象;如果成員變量是靜態屬性,在object可傳入null

//獲得類中所有的變量,但是隻有自己類中的變量,沒有父類繼承過來的變量
			Field[] fieldsAll = animalClass03.getDeclaredFields();
			for(int i=0;i<fieldsAll.length;i++){
				System.out.println(fieldsAll[i].getName());
				fieldsAll[i].setAccessible(true);//private 的變量通過這個設置後,我們也可以爲其賦值了,不然不能訪問
				//如果變量時String類型的,那麼我們就爲這個變量賦值,爲monkey03這個對象中的tile賦值
				if(fieldsAll[0].getType()==String.class){
					fieldsAll[0].set(monkey03, "長尾巴");
				}
				
			}

六、運行demo

        

點擊打開鏈接


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章