天天看點

ParameterizedType應用,java反射,擷取參數化類型的class執行個體

ParameterizedType是一個接口,這個類可以用來檢驗泛型是否被參數化

比如:

class Dao<T>
{
    public Dao(){
        
    }
}      

上面的這個類,也就是泛型類,當有子類內建它的時候,子類也許會将其參數化,當然也可能不進行參數化

比如我們在這樣的子類中:

class SubDao extends Dao<Student>

{

}

這個我們就是在子類內建的時候将Dao<T>這個泛型參數化了

我們在Dao層對資料庫進行操作常常需要得到的是實體的class類,也就是上面的Student這個實體類,我們得到其class執行個體之後就可以利用反射擷取到裡面的實體類中各種方法和變量,進而我們可以為實體類進行操作

那麼如何在Dao層擷取到實體類的class執行個體成為了這一切操作的基礎

下面這些方法我們可以擷取到class執行個體,其實應該知道的是當我們在在StudnetDao層來調用Dao類中的方法時候,其實調用的已經被參數化的Dao,也就是這個方法是Dao<Student>中的,因為我們StudnetDao既然要調用Dao層的方法當然要繼承Dao層,而且在繼承的時候進行參數化,換個方式說:

class Dao<T>
{
  public Dao()
  {
    
  }
  public T get()
  {
    return null;
  }
}      

我們要調用上面的get方法,其實我們在StudnetDao裡面調用的已經不是上面的Dao<T>中的get方法了,而是

class Dao<Student>
{
  public Dao(){
    
  }
  public Student get()
  {
    
  }
}      

這個Dao<Student>裡面的get方法,其實這個類我們是看不到的,因為繼承關系,是以在我們子類的構造函數執行的時候就會生成這個類,這樣我們隻需要寫一個泛型化的Dao<T>類,在StudnetDao,CourseDao對其實作繼承并且參數化,我們的Dao裡面的 方法就可以重複的使用了,進而實作了代碼的複用。

我們現在就是遇到的問題更加的清晰了,我們現在需要在Dao<Student>類裡面,或者是Dao<T>裡面獲得實體Student的一個class執行個體,那麼我們需要記性判斷,判斷什麼,在子類繼承的時候到底有沒有進行參數化

如何判斷:有這樣的一個方法我們可以擷取到目前類的父類

也就是我們在子類中執行擷取其父類superclass,判斷superclass是Dao<T>還是Dao<Student>就可以知道是不是Dao<T>是不是被參數化了

其實這個地方有一個基礎的,需要我們注意就是子類在執行自己的構造方法的時候,我們知道也會執行父類的構造方法,那麼在執行父類的構造方法的時候,裡面的 this表示的是父類還是自己

Type superclass=this.getClass().getGenericSuperClass();

這個我們是放在Dao的構造方法中,但是在子類的構造方法執行的時候,調用super(),這個地方的this是指的子類,也就是StudentDao這個類,這樣我們就獲得了StudentDao的父類superclass

那麼我們并不知道superclass到底是指的Dao<T>還是Dao<Student>,在判斷superclass是否被參數化之前,我們有必要說一下Type這個接口 API文檔中是這樣寫道:

"Type 是 Java 程式設計語言中所有類型的公共進階接口。它們包括原始類型、參數化類型、數組類型、類型變量和基本類型。"

不管怎樣,Type是一個接口,表示類型,我們的superclass就是一個類型,

下面我們要歲superclass進行判斷:

我們判斷用到了另外的一個接口,通過判斷superclass是否為這個接口的一個執行個體,來判斷superclass是否被執行個體化

這個接口是:

ParameterizedType 

如果superclass是該接口的一個執行個體化對象就表示superclass被參數化了,也就是superclass:Dao<Student>,當然如果不是這個接口的一個執行個體就表示是沒有被參數化,superclass:Dao<T>

我們這樣來進行判斷:

if(superclass instanceof ParameterizedType)

{

    當Dao<T> 這個泛型類被參數化之後執行。。。。。

}

我們現在已經知道Dao<T>是否被參數化了,現在我們要做的事情就會擷取到T,如何擷取

在ParameterizedType中有一個方法:GetActualTypeArguments()這個方法的傳回值是一個Type的數組

裡面存的就是我們的要的T

我們可以這樣建立一個參數化類型的變量:

ParameterizedType  parameterizedtype=null;

parameterizedtype=(ParameterizedType)superclass;

Type tys[]=parameterizedtype.getActualTypeArguments();

其實這個地方我們就獲得到了T(Student)并且存儲到了Type的數組中

if(tys!=null && tys.length>0)

{

    clazz=(Class)type[0];

}

這樣我們就擷取到了T的類型,并且得到得到了一個class執行個體,我們下面就可以利用反射擷取到裡面的方法和屬性并操作

,具體代碼如下:

public class Dao<T> {
    private static PreparedStatement st = null;
    public Class clazz;
    public Dao() {
        Type superclass = getClass().getGenericSuperclass();
        ParameterizedType parameterizedType = null;
        if (superclass instanceof ParameterizedType) {
            parameterizedType = (ParameterizedType) superclass;
            Type[] typeArray = parameterizedType.getActualTypeArguments();
            if (typeArray != null && typeArray.length > 0) {
                  clazz=(Class)typeArray[0];
        
            }
        }
    }      
}      

希望對你有所幫助!