最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中獲取泛型類型信息的方法

 更新時(shí)間:2023年03月08日 09:56:18   作者:騎個(gè)小蝸牛  
本文主要介紹了Java中獲取泛型類型信息的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

根據(jù)使用泛型位置的不同可以分為:聲明側(cè)泛型、使用側(cè)泛型。

聲明側(cè)的泛型信息被記錄在Class文件的Constant pool中以Signature的形式保存。而使用側(cè)的泛型信息并沒有保存。

聲明側(cè)泛型

聲明側(cè)泛型包括:

  • 泛型類,或泛型接口的聲明
  • 帶有泛型參數(shù)的成員變量
  • 帶有泛型參數(shù)的方法

使用側(cè)泛型

使用側(cè)泛型包括:

  • 方法的局部變量,
  • 方法調(diào)用時(shí)傳入的變量

獲取泛型類型相關(guān)方法

上文有提到,聲明側(cè)的泛型被記錄在Class文件的Constant pool中以Signature的形式保存。

JDK的Class、Field、Method類提供了一系列的獲取泛型類型的相關(guān)方法。

1. Class類的泛型方法

Type getGenericSuperclass():獲取父類的Type

  • 若父類有泛型,返回的實(shí)際Type是ParameterizedType接口的實(shí)現(xiàn)類ParameterizedTypeImpl類
  • 若父類無泛型,返回的實(shí)際Type是Class類

Type[] getGenericInterfaces():獲取父接口的Type集合

  1. 若父類有泛型,返回的實(shí)際Type是ParameterizedType接口的實(shí)現(xiàn)類ParameterizedTypeImpl類
  2. 若父類無泛型,返回的實(shí)際Type是Class類

2. Field類的泛型方法

Type getGenericType():獲取字段的Type

  • 若字段有泛型,返回的實(shí)際Type是ParameterizedType接口的實(shí)現(xiàn)類ParameterizedTypeImpl類
  • 若字段無泛型,返回的實(shí)際Type是Class類

3. Method類的泛型方法

Type getGenericReturnType():獲取方法返回值的Type

  • 若返回值有泛型,返回的實(shí)際Type是ParameterizedType接口的實(shí)現(xiàn)類ParameterizedTypeImpl類
  • 若返回值無泛型,返回的實(shí)際Type是Class類

Type[] getGenericParameterTypes():獲取方法參數(shù)的Type集合

  • 若方法參數(shù)有泛型,返回的實(shí)際Type是ParameterizedType接口的實(shí)現(xiàn)類ParameterizedTypeImpl類
  • 若方法參數(shù)無泛型,返回的實(shí)際Type是Class類

Type[] getGenericExceptionTypes():獲取方法聲明的異常的Type集合

  • 若方法參數(shù)有泛型,返回的實(shí)際Type是ParameterizedType接口的實(shí)現(xiàn)類ParameterizedTypeImpl類
  • 若方法參數(shù)無泛型,返回的實(shí)際Type是Class類

4. ParameterizedType類

ParameterizedType是Type的子接口,表示參數(shù)化類型,用于獲取泛型的參數(shù)類型。

ParameterizedType的主要方法:

  • Type[] getActualTypeArguments():獲取實(shí)際類型參數(shù)的Type集合
  • Type getRawType():獲取聲明此類型的類或接口的Type
  • Type getOwnerType():如果聲明此類型的類或接口為內(nèi)部類,這返回的是該內(nèi)部類的外部類的Type(也就是該內(nèi)部類的擁有者)

獲取聲明側(cè)的泛型類型信息

  • 泛型類,或泛型接口的聲明
  • 帶有泛型參數(shù)的成員變量
  • 帶有泛型參數(shù)的方法

示例:

public class MyTest extends TestClass<String> implements TestInterface1<Integer>,TestInterface2<Long> {

? ? private List<Integer> list;

? ? private Map<Integer, String> map;

? ? public List<String> aa() {
? ? ? ? return null;
? ? }

? ? public void bb(List<Long> list) {

? ? }

? ? public static void main(String[] args) throws Exception {
? ? ? ? System.out.println("======================================= 泛型類聲明的泛型類型 =======================================");
? ? ? ? ParameterizedType parameterizedType = (ParameterizedType)MyTest.class.getGenericSuperclass();
? ? ? ? System.out.println(parameterizedType.getTypeName() + "--------->" + parameterizedType.getActualTypeArguments()[0].getTypeName());

? ? ? ? Type[] types = MyTest.class.getGenericInterfaces();
? ? ? ? for (Type type : types) {
? ? ? ? ? ? ParameterizedType typ = (ParameterizedType)type;
? ? ? ? ? ? System.out.println(typ.getTypeName() + "--------->" + typ.getActualTypeArguments()[0].getTypeName());
? ? ? ? }

? ? ? ? System.out.println("======================================= 成員變量中的泛型類型 =======================================");
? ? ? ? ParameterizedType parameterizedType1 = (ParameterizedType)MyTest.class.getDeclaredField("list").getGenericType();
? ? ? ? System.out.println(parameterizedType1.getTypeName() + "--------->" + parameterizedType1.getActualTypeArguments()[0].getTypeName());

? ? ? ? ParameterizedType parameterizedType2 = (ParameterizedType)MyTest.class.getDeclaredField("map").getGenericType();
? ? ? ? System.out.println(parameterizedType2.getTypeName() + "--------->" + parameterizedType2.getActualTypeArguments()[0].getTypeName()+","+parameterizedType2.getActualTypeArguments()[1].getTypeName());

? ? ? ? System.out.println("======================================= 方法參數(shù)中的泛型類型 =======================================");
? ? ? ? ParameterizedType parameterizedType3 = (ParameterizedType)MyTest.class.getMethod("aa").getGenericReturnType();
? ? ? ? System.out.println(parameterizedType3.getTypeName() + "--------->" + parameterizedType3.getActualTypeArguments()[0].getTypeName());

? ? ? ? System.out.println("======================================= 方法返回值中的泛型類型 =======================================");
? ? ? ? Type[] types1 = MyTest.class.getMethod("bb", List.class).getGenericParameterTypes();
? ? ? ? for (Type type : types1) {
? ? ? ? ? ? ParameterizedType typ = (ParameterizedType)type;
? ? ? ? ? ? System.out.println(typ.getTypeName() + "--------->" + typ.getActualTypeArguments()[0].getTypeName());
? ? ? ? }
? ? }
}

class TestClass<T> {

}

interface TestInterface1<T> {

}

interface TestInterface2<T> {

}

輸出

======================================= 泛型類聲明的泛型類型 =======================================
com.joker.test.generic.TestClass<java.lang.String>--------->java.lang.String
com.joker.test.generic.TestInterface1<java.lang.Integer>--------->java.lang.Integer
com.joker.test.generic.TestInterface2<java.lang.Long>--------->java.lang.Long
======================================= 成員變量中的泛型類型 =======================================
java.util.List<java.lang.Integer>--------->java.lang.Integer
java.util.Map<java.lang.Integer, java.lang.String>--------->java.lang.Integer,java.lang.String
======================================= 方法參數(shù)中的泛型類型 =======================================
java.util.List<java.lang.String>--------->java.lang.String
======================================= 方法返回值中的泛型類型 =======================================
java.util.List<java.lang.Long>--------->java.lang.Long

獲取使用側(cè)的泛型類型信息

上面講的相關(guān)類的獲取泛型類型相關(guān)方法都只是針對(duì)聲明側(cè)的泛型。因?yàn)槁暶鱾?cè)的泛型被記錄在Class文件的Constant pool中以Signature的形式保存。所以Java提供了相關(guān)方法能獲取到這些信息。

那使用側(cè)的泛型信息怎么獲取呢?由于使用側(cè)的泛型信息在編譯期的時(shí)候就被類型擦除了,所以運(yùn)行時(shí)是沒辦法獲取到這些泛型信息的。

難道就真的沒辦法了嗎,其實(shí)還是有的。使用側(cè)需要獲取泛型信息的地方主要是:方法調(diào)用時(shí)傳入的泛型變量,通常需要在方法中獲取變量的泛型類型。比如在JSON解析(反序列化)的場景,他們是怎么實(shí)現(xiàn)的了。

針對(duì)獲取使用側(cè)的泛型類型信息,主要實(shí)現(xiàn)方案是通過匿名內(nèi)部類。

Gson中的泛型抽象類TypeToken<T>,F(xiàn)astJson中的泛型類TypeReference<T>等就是用的該方案。

匿名內(nèi)部類實(shí)現(xiàn)獲取使用側(cè)的泛型類型

上文有講到,在聲明側(cè)的泛型中,針對(duì)泛型類或泛型接口的聲明的泛型,Class類提供了getGenericSuperclass()、getGenericInterfaces()來獲取其子類(實(shí)現(xiàn)類)上聲明的具體泛型類型信息。

而匿名內(nèi)部類是什么?其本質(zhì)就是一個(gè)繼承/實(shí)現(xiàn)了某個(gè)類(接口,普通類,抽象類)的子類匿名對(duì)象。

匿名內(nèi)部類實(shí)現(xiàn)獲取使用側(cè)的泛型類型的原理:

  • 定義泛型類,泛型類中有一個(gè)Type類型的字段,用于保存泛型類型的Type
  • 通過匿名內(nèi)部類的方式創(chuàng)建該泛型類的子類實(shí)例(指定了具體的泛型類型)
    在創(chuàng)建子類實(shí)例的構(gòu)造方法中,已經(jīng)通過子類的Class的getGenericSuperclass()獲取到了泛型類型信息并復(fù)制給了Type類型的字段中。
  • 隨后任何地方,只要得到了該子類實(shí)例,就可以通過實(shí)例得到泛型類型的Type,這就得到了使用側(cè)的泛型類信息。

簡單示例:

定義泛型類TestClass2<T>,類中包含字段Type

public abstract class TestClass2<T> {

? ? private final Type type;

? ? public TestClass2() {
? ? ? ? Type superClass = getClass().getGenericSuperclass();
? ? ? ? if (!(superClass instanceof ParameterizedType)) {
? ? ? ? ? ? throw new IllegalArgumentException("無泛型類型信息");
? ? ? ? }
? ? ? ? type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
? ? }

? ? public Type getType() {
? ? ? ? return type;
? ? }
}

測試獲取泛型類型

public class Test {

? ? public static ?<T> T get(TestClass2<T> tTestClass2) throws IllegalAccessException, InstantiationException {
? ? ? ? Type type = tTestClass2.getType();
? ? ? ? Class clazz = (Class) type;
? ? ? ? return (T)clazz.newInstance();
? ? }

? ? public static void main(String[] args) throws InstantiationException, IllegalAccessException {
? ? ? ? String str = get(new TestClass2<String>() {});
? ? ? ? Date date = get(new TestClass2<Date>() {});
? ? }
}

到此這篇關(guān)于Java中獲取泛型類型信息的方法的文章就介紹到這了,更多相關(guān)Java獲取泛型類型信息內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java微服務(wù)Nacos Config配置中心超詳細(xì)講解

    Java微服務(wù)Nacos Config配置中心超詳細(xì)講解

    配置文件相對(duì)分散。在一個(gè)微服務(wù)架構(gòu)下,配置文件會(huì)隨著微服務(wù)的增多變的越來越多,而且分散 在各個(gè)微服務(wù)中,不好統(tǒng)一配置和管理。每一個(gè)環(huán)境所使用的配置理論上都是不同的,一旦需要修改,就需要我們?nèi)ジ鱾€(gè)微服務(wù)下手動(dòng)維護(hù)
    2023-02-02
  • maven?插件?assembly?打tar.gz包的詳細(xì)過程

    maven?插件?assembly?打tar.gz包的詳細(xì)過程

    這篇文章主要介紹了maven插件assembly打tar.gz包的詳細(xì)過程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • Spring Cloud Zuul集成Swagger實(shí)現(xiàn)過程解析

    Spring Cloud Zuul集成Swagger實(shí)現(xiàn)過程解析

    這篇文章主要介紹了Spring Cloud Zuul集成Swagger實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • mybatis一級(jí)緩存和二級(jí)緩存的區(qū)別及說明

    mybatis一級(jí)緩存和二級(jí)緩存的區(qū)別及說明

    這篇文章主要介紹了mybatis一級(jí)緩存和二級(jí)緩存的區(qū)別及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • java實(shí)現(xiàn)6種字符串?dāng)?shù)組的排序(String array sort)

    java實(shí)現(xiàn)6種字符串?dāng)?shù)組的排序(String array sort)

    這篇文章主要介紹了java實(shí)現(xiàn)6種字符串?dāng)?shù)組的排序(String array sort),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • SpringBoot整合Ureport2報(bào)表及常見使用方法

    SpringBoot整合Ureport2報(bào)表及常見使用方法

    這篇文章主要介紹了SpringBoot整合Ureport2報(bào)表及常見使用方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表

    SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表

    本文主要介紹了SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 精致小巧的java相冊制作方法

    精致小巧的java相冊制作方法

    這篇文章主要為大家詳細(xì)介紹了精致小巧的java相冊制作方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • idea中如何連接hive

    idea中如何連接hive

    這篇文章主要介紹了idea中如何連接hive問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • mybatis@insert?注解如何判斷insert或是update

    mybatis@insert?注解如何判斷insert或是update

    這篇文章主要介紹了mybatis@insert?注解如何判斷insert或是update,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07

最新評(píng)論

瑞安市| 长丰县| 福海县| 潞西市| 海原县| 左贡县| 苍梧县| 黄浦区| 新民市| 乐至县| 理塘县| 无棣县| 阿尔山市| 襄城县| 中西区| 慈溪市| 新晃| 缙云县| 利川市| 廊坊市| 金坛市| 樟树市| 囊谦县| 上栗县| 达孜县| 海伦市| 顺昌县| 雷波县| 清原| 甘泉县| 大荔县| 思南县| 邻水| 宁远县| 利津县| 普兰店市| 凭祥市| 宁陵县| 孟州市| 常熟市| 花莲市|