Reflection(反射)是Java被視爲動態語言的關鍵,反射機制容許程序在執行期藉助於Reflection API取得任何類的內部信息,並能直接操做任意對象的內部屬性及方法。數組
Java反射機制主要提供瞭如下功能:框架
一、在運行時構造任意一個類的對象spa
二、在運行時獲取任意一個類所具備的成員變量和方法代理
三、在運行時調用任意一個對象的方法(屬性)對象
四、生成動態代理繼承
咱們通常是經過某一個類的 Class類的實例來進行獲取某一個類中的方法以下代碼:get
Class clazz = Class.forName(「全類名」);源碼
Method[] methods = clazz. getDeclaredMethods(); io
Class 對象獲取 Method 的方法:class
Method getDeclaredMethod(String name, Class<?>... parameterTypes)
Method[] getDeclaredMethods()
Method getMethod(String name, Class<?>... parameterTypes)
Method[] getMethods()
其中getMethod 、getMethods只能獲取本類及從父類中繼承過來的公有方法,而getDeclaredMethod、getDeclaredMethods 只能夠獲取本類中定義的方法(包括私有方法)!其中getDeclaredMethod 、getDeclaredMethods 較爲經常使用!
那麼當咱們獲取到某一個類中的方法時,咱們怎麼來進行執行該方法呢?
Method 對象的方法:
Object invoke(Object obj, Object... args)
其中該方法的第一個參數是類哪個對象來調用方法,第二個參數是方法中有哪些參數!
咱們通常是經過Method 對象調用 invoke() 方法,來進行執行相關方法。
同理對於某一個類中的字段咱們也能夠經過反射來獲取!其獲取的方法以下代碼:
Class clazz = Class.forName(「全類名」);
Field[] fields = clazz. getDeclaredFields();
Class 對象獲取 Field 的方法:
Field getDeclaredField(String name)
Field[] getDeclaredFields()
Field getField(String name)
Field[] getFields()
其中getField 、getFields只能獲取本類及從父類中繼承過來的公有字段,而getDeclaredField、getDeclaredFields 只能夠獲取本類中定義的字段(包括私有字段)!
一樣咱們也能夠爲字段進行設置和獲取字段的值
Object get(Object obj) 返回指定對象上此 Field 表示的字段的值。
void set(Object obj, Object value) 將指定對象變量上此 Field 對象表示的字段設置爲指定的新值。
具體能夠參看 Java API。
以下咱們結合着代碼來看一下泛型和反射(到後期咱們使用框架時,咱們看它們的源碼時就會發現有大量的反射與泛型結合的代碼)!
以下代碼:
JavaBean:
public class Person{
//私有屬性。
//相應的getting和setting方法。
//空構造器(利用反射建立對象時進行調用來使用)。
}
泛型類:
public class Dao<T>{
public T select(int id ){
// 就不寫方法的實現了,直接return null了,就不返回T類型的對象了!
return null;
}
}
繼承泛型的相關類:
public class PersonDao extends Dao<Person>{
// ... ...
}
public class Test{
public static viod main(String[] args){
PersonDao pDao = new PersonDao();
Person person = pDao.select(1);//如何來返回Person類型的對象?
}
}
此時對於咱們來講咱們不進行建立對象,交由反射來爲咱們進行建立返回的 T 類型對象(在此處建立的返回類型應該是Person類型的對象) ,對於泛型而言咱們知道其不能使用 .class 屬性!那這樣怎麼返回 T 類型(Person類型)的對象呢?在此咱們可以獲取繼承泛型類 Dao<T> 的PersonDao類的 Class 類型的對象,咱們可使用Class clazz = Class.forName(「全類名」); 來獲取PersonDao的Class 類型的對象, 而後經過使用Type getGenericSuperclass()獲得帶泛型類型的父類的Type類型的對象,即獲得Dao<T> :Dao<Person>。此時已經將T類型實例化爲Person類型了,通常咱們還須要判斷一下其是不是帶類型參數的類型ParameterizedType,經過if( type instanceof ParameterizedType)來判斷,若是是而後經過ParameterizedType getActualTypeArguments() 方法獲取到實際的泛型類型參數數組。即獲取到 Person類型的Class 實例。進而經過是newInstance() 方法獲得 Person類型的對象。進而返回!
能夠參考下面的代碼進行理解:
public static Class<?> getActualTypeArgumentsByGenericSuperclass(Class<?> clazz, int index) {
Type genericSuperclass = clazz.getGenericSuperclass();
//判斷其是不是帶類型參數的類型
if (!(genericSuperclass instanceof ParameterizedType)) {
return Object.class;
}
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
//獲取到實際的泛型類型參數數組.
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (index > actualTypeArguments.length-1|| index<0) {
return Object.class;
}
if (!(actualTypeArguments[index] instanceof Class)) {
return Object.class;
}
return (Class<?>) actualTypeArguments[index];
}