對於反射的一些總結(二)

1.  反射(Reflection):

1.1.   接下來就讓咱們來聊一下什麼叫反射?

        Reflection(反射)是Java被視爲動態語言的關鍵,反射機制容許程序在執行期藉助於Reflection API取得任何類的內部信息,並能直接操做任意對象的內部屬性及方法。數組

Java反射機制主要提供瞭如下功能:框架

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

    二、在運行時獲取任意一個類所具備的成員變量和方法代理

    三、在運行時調用任意一個對象的方法(屬性)對象

    四、生成動態代理繼承

1.2.   如何經過反射來獲取任意一個類中所具備的方法?

      咱們通常是經過某一個類的 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() 方法,來進行執行相關方法。

1.3.   如何經過反射來獲取某一個類中的字段?

同理對於某一個類中的字段咱們也能夠經過反射來獲取!其獲取的方法以下代碼:

    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。

1.4.   接下來進說一下關於泛型和反射!

 以下咱們結合着代碼來看一下泛型和反射(到後期咱們使用框架時,咱們看它們的源碼時就會發現有大量的反射與泛型結合的代碼)!

以下代碼:

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];

       }

相關文章
相關標籤/搜索