java怎樣動(dòng)態(tài)獲取泛型參數(shù)的類型
Java如何動(dòng)態(tài)獲取泛型參數(shù)的類型
我們都知道java中的泛型其實(shí)是偽泛型,java在編譯階段會(huì)對(duì)變異類型進(jìn)行擦除,擦出到泛型類的最小上限,編譯后得到的class文件里面是沒有任何泛型信息的,泛型的控制其實(shí)就是java編譯器進(jìn)行的控制,編譯階段進(jìn)行泛型檢查。
那如果我們想在運(yùn)行時(shí)知道泛型類的類型,如何做到呢?
主要用到下面幾個(gè)api:
1、public Type getGenericSuperclass()---Class類的方法
2、Type[] getActualTypeArguments()---ParameterizedType方法
3、public Type[] getGenericInterfaces()---Class類的方法
- 我們先定義一個(gè)泛型類:
public class Father<T> {
}- 再定義一個(gè)子類:
public class Son extends Father<String>{
}- 先來看看下面代碼:
System.out.println(Son.class.getGenericSuperclass()); System.out.println(Son.class.getSuperclass()); System.out.println(Father.class.getGenericSuperclass()); System.out.println(Father.class.getSuperclass());
運(yùn)行結(jié)果如下:

從上面運(yùn)行結(jié)果可以看出兩點(diǎn):
(1)通過Class類的getGenericSuperclass()是可以獲取到泛型信息的;
(2)泛型類本身是無法獲取到泛型信息的,只能通過泛型類的子類來獲取泛型信息,這也很好解釋,因?yàn)榉盒皖惐热鏔ather類自身,其泛型參數(shù)并未確定,自然無法獲取泛型信息,而子類的泛型參數(shù)類型已經(jīng)確定,父類泛型信息已經(jīng)確定,所以可以查詢。
具體的查詢泛型參數(shù)類型的代碼如下:
ParameterizedType parameterizedType = (ParameterizedType) Son.class.getGenericSuperclass();
System.out.println(parameterizedType.getClass().getName());
System.out.println(parameterizedType);
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for(Type actualTypeArgument: actualTypeArguments) {
System.out.println(actualTypeArgument.getClass().getName());
System.out.println(actualTypeArgument);
} 運(yùn)行結(jié)果如下:

由上圖運(yùn)行結(jié)果可知:
(1)getGenericSuperclass()返回的實(shí)際類型為ParameterizedTypeImpl,這里面帶有父類的泛型類型信息;
(2)獲取泛型參數(shù)信息是通過ParameterizedType的getActualTypeArguments方法,該方法返回的是一個(gè)Type類型的數(shù)據(jù),該數(shù)據(jù)存放的數(shù)據(jù)的實(shí)際類型為Class,也就是我們得到了泛型參數(shù)的類信息。
上面講述的是獲取父類的泛型類型,那接口的泛型類型如何獲取呢?
- 先貼一個(gè)簡單的接口:
public interface ITest<T> {
}- 我們讓Son類實(shí)現(xiàn)該方法:
public class Son extends Father<String> implements ITest<Integer>{
}- 獲取ITest的泛型參數(shù)類型的方法如下:
ParameterizedType parameterizedType = (ParameterizedType) Son.class.getGenericInterfaces()[0];
System.out.println(parameterizedType.getClass().getName());
System.out.println(parameterizedType);
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for(Type actualTypeArgument: actualTypeArguments) {
System.out.println(actualTypeArgument.getClass().getName());
System.out.println(actualTypeArgument);
} 運(yùn)行結(jié)果如下:

和泛型類區(qū)別就是getGenericSuperclass()方法換成了getGenericInterfaces(),getGenericInterfaces()方法返回的是Type[],因?yàn)橐粋€(gè)類可以實(shí)現(xiàn)多個(gè)接口,所以想要獲取哪個(gè)接口的泛型信息,需要指定數(shù)據(jù)下標(biāo),這里Son類就實(shí)現(xiàn)了一個(gè)接口,所以直接Son.class.getGenericInterfaces()[0]就可以了。
上面的代碼有一個(gè)共同點(diǎn)
就是泛型類或者泛型接口已經(jīng)有一個(gè)子類了,通過子類的Class信息可以獲取到泛型父類或者泛型接口的泛型類型信息,那么如果沒有子類,怎么直接獲取泛型類的泛型類型信息呢?
很簡單,通過匿名內(nèi)部類(其實(shí)還是通過子類).
new Father<Integer>() {}.getClass().getGenericSuperclass();
new ITest<Integer>() {}.getClass().getGenericInterfaces())[0];總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot+MinIO實(shí)現(xiàn)對(duì)象存儲(chǔ)的示例詳解
MinIO?是一個(gè)基于Apache?License?v2.0開源協(xié)議的對(duì)象存儲(chǔ)服務(wù),它是一個(gè)非常輕量的服務(wù),可以很簡單的和其他應(yīng)用的結(jié)合,所以下面我們就來看看SpringBoot如何整合MinIO實(shí)現(xiàn)對(duì)象存儲(chǔ)吧2023-10-10
基于SpringBoot實(shí)現(xiàn)用戶身份驗(yàn)證工具
這篇文章主要介紹了基于SpringBoot實(shí)現(xiàn)的用戶身份驗(yàn)證工具,非常不錯(cuò),具有參考借鑒價(jià)值 ,需要的朋友可以參考下2018-04-04
java中l(wèi)ist使用時(shí)需避免的場景總結(jié)
眾所周知,Java為開發(fā)者提供了多種集合類的實(shí)現(xiàn),其中幾乎所有業(yè)務(wù)代碼都需要用到List,但List的錯(cuò)誤使用也會(huì)導(dǎo)致諸多問題,所以本文我們就來看一看幾個(gè)錯(cuò)誤使用List的場景吧2023-10-10
java教程散列表和樹所對(duì)應(yīng)容器類及HashMap解決沖突學(xué)習(xí)
本篇篇文章是java教程,主要介紹了java教程散列表,樹所對(duì)應(yīng)容器類及HashMap解決沖突的學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10
劍指Offer之Java算法習(xí)題精講數(shù)組查找與字符串交集
跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化2022-03-03
Spring實(shí)戰(zhàn)之類級(jí)別緩存實(shí)現(xiàn)與使用方法
這篇文章主要介紹了Spring實(shí)戰(zhàn)之類級(jí)別緩存實(shí)現(xiàn)與使用方法,結(jié)合實(shí)例形式分析了Spring類級(jí)別緩存配置、屬性、領(lǐng)域模型等相關(guān)操作技巧,需要的朋友可以參考下2020-01-01

