java在運(yùn)行時(shí)獲取泛型類型

一個(gè)簡(jiǎn)單場(chǎng)景:一個(gè)處理函數(shù),需要傳入處理結(jié)果監(jiān)聽(tīng)來(lái)響應(yīng)結(jié)果,響應(yīng)結(jié)果是一個(gè)JSON字符串,且要將其轉(zhuǎn)換成對(duì)象再交給監(jiān)聽(tīng)進(jìn)行處理,由于對(duì)象類型存在多種,所以需要采用泛型。

這樣會(huì)存在一個(gè)需求,即將響應(yīng)結(jié)果轉(zhuǎn)換成相應(yīng)的類型。為了達(dá)到該需求,我們一般會(huì)再傳入一個(gè)Class來(lái)協(xié)助進(jìn)行類型轉(zhuǎn)換

結(jié)果響應(yīng)監(jiān)聽(tīng)器:

public interface IProcessResponse<T> {
public void onProcessCompleted(T result);
}

處理函數(shù):

public class Test {

public <T> void process(Class<T> reponseClass
,IProcessResponse<T> processResponseListener){
String content = runProcess();

Gson gson = new Gson();
T responese = gson.fromJson(content, reponseClass);
processResponseListener.onProcessCompleted(responese);
}
}

這樣處理很好,沒(méi)有什么問(wèn)題,但是我有一個(gè)疑問(wèn),既然監(jiān)聽(tīng)器里已經(jīng)帶了T,它的類型實(shí)際上就是參數(shù)reponseClass參數(shù)所表示的,為什么還要傳一個(gè)

Class<T> reponseClass

這個(gè)參數(shù),難道不能直接獲取到T所表示的Class嗎?

那么就引入了本篇要研究的主題,即如何在運(yùn)行時(shí)獲取泛型的類型。

最直接的嘗試:使用T.getClass()或者T.class。嘗試后發(fā)現(xiàn)T并沒(méi)有相應(yīng)的接口函數(shù)供使用

那就只能從實(shí)際的對(duì)象著手,即通過(guò)變量processResponseListener來(lái)取,因?yàn)閭魅氲氖菍?shí)際存在的對(duì)象,可以通過(guò)反射獲取泛型類型,改造一下process函數(shù):

public <T> void process(IProcessResponse<T> processResponseListener){
String content = runProcess();

Gson gson = new Gson();

Type[] types = processResponseListener.getClass().getGenericInterfaces();
Type[] params = ((ParameterizedType) types[0]).getActualTypeArguments();
Class<T> reponseClass = (Class) params[0];


T responese = gson.fromJson(content, reponseClass);

processResponseListener.onProcessCompleted(responese);
}

getClass():獲取的是實(shí)際運(yùn)行的類的字節(jié)碼

getGenericInterfaces():以Type數(shù)組的形式返回本類直接實(shí)現(xiàn)的接口列表,包含了泛型參數(shù)信息

getActualTypeArguments() :獲取泛型類型的實(shí)際類型參數(shù)集

另一種情況:

假設(shè)我們的監(jiān)聽(tīng)器不是一個(gè)接口,而是一個(gè)抽象類:

public abstract class AbstractProcessResponse<T> {
public abstract void onProcessCompleted(T result);
private void commonProcess(){}
}

處理函數(shù)直接仿造 :

public <T> void process(IProcessResponse<T> processResponseListener)

函數(shù),得到:

public <T> void process(AbstractProcessResponse<T> processResponseListener){
String content = runProcess();

Gson gson = new Gson();

Type[] types = processResponseListener.getClass().getGenericInterfaces();
Type[] params = ((ParameterizedType) types[0]).getActualTypeArguments();
Class<T> reponseClass = (Class) params[0];


T responese = gson.fromJson(content, reponseClass);

processResponseListener.onProcessCompleted(responese);
}

上面能得到正確結(jié)果嗎?看getGenericInterfaces()方法的作用:

???? 以Type數(shù)組的形式返回本類直接實(shí)現(xiàn)的接口列表,包含了泛型參數(shù)信息

很明顯傳入的AbstractProcessResponse<T>類型參數(shù)將是一個(gè)繼承該抽象類的子類,所以getGenericInterfaces()取到的Type[]數(shù)組元素個(gè)數(shù)為0,上面的函數(shù)執(zhí)行將會(huì)拋出異常

?? 經(jīng)改造,正確的函數(shù)如下:

public <T> void process(AbstractProcessResponse<T> processResponseListener){
String content = runProcess();

Gson gson = new Gson();

Type type = processResponseListener.getClass().getGenericSuperclass();
Type[] params = ((ParameterizedType) type).getActualTypeArguments();
Class<T> reponseClass = (Class) params[0];

T responese = gson.fromJson(content, reponseClass);

processResponseListener.onProcessCompleted(responese);
}

getGenericSuperclass() :返回表示當(dāng)前Class 所表示的實(shí)體(類、接口、基本類型或 void)的直接超類的Type

最后總結(jié)一下:

對(duì)于實(shí)現(xiàn)接口而來(lái)的對(duì)象,使用getGenericInterfaces()與getActualTypeArguments()

對(duì)于繼承父類而來(lái)的對(duì)象,使用getGenericSuperclass()與getActualTypeArguments()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 對(duì)象的創(chuàng)建與銷毀 Item 1: 使用static工廠方法,而不是構(gòu)造函數(shù)創(chuàng)建對(duì)象:僅僅是創(chuàng)建對(duì)象的方法,并非Fa...
    孫小磊閱讀 2,186評(píng)論 0 3
  • 前言 人生苦多,快來(lái) Kotlin ,快速學(xué)習(xí)Kotlin! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,761評(píng)論 9 118
  • object 變量可指向任何類的實(shí)例,這讓你能夠創(chuàng)建可對(duì)任何數(shù)據(jù)類型進(jìn)程處理的類。然而,這種方法存在幾個(gè)嚴(yán)重的問(wèn)題...
    CarlDonitz閱讀 1,030評(píng)論 0 5
  • 為什么普通的果子產(chǎn)生了神奇的效果? 一. 需要克服的概念 1. 什么是藥食同源: 食物與藥物沒(méi)有明確的界限,藥物與...
    吉祥娘恒慈閱讀 54,165評(píng)論 0 2
  • 轉(zhuǎn)眼,2017年又已過(guò)了大半,我腦中一直浮現(xiàn)出一幅畫(huà)面,那是一個(gè)星期三的下午,我照例開(kāi)車去美術(shù)館上課,在一...
    浮萍不浮閱讀 283評(píng)論 0 0

友情鏈接更多精彩內(nèi)容