標籤:需要 array 類型 except nbsp ide 通用 ring inter
java反射機制
Person p=new Person();
這是什麼?當然是執行個體化一個對象了.可是這種執行個體化對象的方法存在一個問題,那就是必須要知道類名才可以執行個體化它的對象,這樣我們在應用方面就會受到限制.那麼有沒有這樣一種方式,讓我們不知道這個類的類名就可以執行個體化它的對象呢?Thank Goodness!幸虧我們用的是java, java就提供了這樣的機制.
1).java程式在運行時可以獲得任何一個類的位元組碼資訊,包括類的修飾符(public,static等),基類(超類,父類),實現的介面,欄位和方法等資訊.
2).java程式在運行時可以根據位元組碼資訊來建立該類的執行個體對象,改變對象的欄位內容和調用對象方法.
這樣的機制就叫反射技術.可以想象光學中的反射,就像我們照鏡子,鏡子中又出現一個自己(比喻可能不太恰當,但是足以表達清楚意思了).反射技術提供了一種通用的動態串連程式組件的方法,不必要把程式所需要的目標類寫入程式碼到來源程式中,從而使得我們可以建立靈活的程式.
Java的反射機制是通過反射API來實現的,它允許程式在運行過程中取得任何一個已知名稱的類的內部資訊.反射API位於java.lang.reflect包中.主要包括以下幾類:
1).Constructor類:用來描述一個類的構造方法
2).Field類:用來描述一個類的成員變數
3).Method類:用來描述一個類的方法.
4).Modifer類:用來描述類內各元素的修飾符
5).Array:用來對數組進行操作.
Constructor,Field,Method這三個類都是JVM(虛擬機器)在程式運行時建立的,用來表示載入類中相應的成員.這三個類都實現了java.lang.reflect.Member介面,Member介面定義了擷取類成員或構造方法等資訊的方法.要使用這些反射API,必須先得到要操作的對象或類的Class類的執行個體.通過調用Class類的newInstance方法(只能調用類的預設構造方法)可以建立類的執行個體.這樣有局限性,我們可以先沖類的Class執行個體擷取類需要的構造方法,然後在利用反射來建立類的一個執行個體.
一.擷取類的構造方法的Constructor對象(數組)
● Constructor[] getDeclaredConstructors();返回已載入類聲明的所有的構造方法的Constructor對象數組.
● Constructor getDeclaredConstructor(Class[] paramTypes);返回已載入類聲明的指定構造方法的Constructor對象,paramTypes指定了參數類型.
● Constructor[] getConstructors();返回已載入類聲明的所有的public類型的構造方法的Constructor對象數組.
● Constructor getConstructor(Class[] paramTypes);返回已載入類聲明的指定的public類型的構造方法的Constructor對象,paramTypes指定了參數類型.
如果某個類中沒有定義構造方法,第一個和第三個方法返回的數組中只有一個元素,就是預設的構造方法;如果某個類中只定義了有參數的建構函式,而沒有定義預設建構函式,第一個和第三個方法返回的數組中不包含預設的構造方法.
二.擷取類成員變數的Field對象(數組)
●Field[] getDeclaredFields():返回已載入類聲明的所有成員變數的Field對象數組,不包括從父類繼承的成員變數.
●Field getDeclaredField(String name):返回已載入類聲明的所有成員變數的Field對象,不包括從父類繼承的成員變數,參數name指定成員變數的名稱.
●Field[] getFields():返回已載入類聲明的所有public型的成員變數的Field對象數組,包括從父類繼承的成員變數
●Field getField(String name):返回已載入類聲明的所有成員變數的Field對象,包括從父類繼承的成員變數,參數name指定成員變數的名稱.
三.擷取類的方法的Method對象(數組)
●Method[] getDeclaredMethods():返回已載入類聲明的所有方法的Method對象數組,不包括從父類繼承的方法.
●Method getDeclaredMethod(String name,Class[] paramTypes):返回已載入類聲明的所有方法的Method對象,不包括從父類繼承的方法,參數name指定方法的名稱,參數paramTypes指定方法的參數類型.
●Method[] getMethods():返回已載入類聲明的所有方法的Method對象數組,包括從父類繼承的方法.
●Method getMethod(String name,Class[] paramTypes):返回已載入類聲明的所有方法的Method對象,包括從父類繼承的方法,參數name指定方法的名稱,參數paramTypes指定方法的參數類型.
四.檢索類的其他資訊
●int getModifiers():返回已載入類的修飾符的整形標識值.
●Package getPackage():返回已載入類的包名
●Class getSuperclass():返回已載入類的父類的Class執行個體.
●Class [] getInterfaces():返回已載入類實現的介面的Class對象數組.
●boolean isInterface():返回已載入類是否是介面.
反射的功能很強大,但是使用不當可能會缺點大於優點,反射使代碼邏輯混亂,會帶來維護的問題.
註:
運行時類型識別(Run-time Type Identification, RTTI)主要有兩種方式,一種是我們在編譯時間和運行時已經知道了所有的類型,另外一種是功能強大的“反射”機制。
要理解RTTI在Java中的工作原理,首先必須知道類型資訊在運行時是如何表示的,這項工作是由“Class對象”完成的,它包含了與類有關的資訊。類是程式的重要組成部分,每個類都有一個Class對象,每當編寫並編譯了一個新類就會產生一個Class對象,它被儲存在一個同名的.class檔案中。在運行時,當我們想產生這個類的對象時,運行這個程式的Java虛擬機器(JVM)會確認這個類的Class對象是否已經載入,如果尚未載入,JVM就會根據類名尋找.class檔案,並將其載入,一旦這個類的Class對象被載入記憶體,它就被用來建立這個類的所有對象。一般的RTTI形式包括三種:
1. 傳統的類型轉換。如“(Apple)Fruit”,由RTTI確保類型轉換的正確性,如果執行了一個錯誤的類型轉換,就會拋出一個ClassCastException異常。
2. 通過Class對象來擷取對象的類型。如
Class c = Class.forName(“Apple”);
Object o = c.newInstance();
3. 通過關鍵字instanceof或Class.isInstance()方法來確定對象是否屬於某個特定類型的執行個體,準確的說,應該是instanceof / Class.isInstance()可以用來確定對象是否屬於某個特定類及其所有基類的執行個體,這和equals() / ==不一樣,它們用來比較兩個對象是否屬於同一個類的執行個體,沒有考慮繼承關係。
java反射機制