Java獲取泛型實(shí)際類型的方法詳解
Java反射獲取
獲取類上的泛型
獲取父類定義的泛型
例如現(xiàn)在有一個(gè)父類
public abstract class TestClass<E> { ...... }
同時(shí)他有多個(gè)實(shí)現(xiàn)類,如
public class TestStringClass extends TestClass<String>{ .... } public class TestIntegerClass extends TestClass<Integer>{ .... } ....
此時(shí)如果要獲取該類上聲明的泛型
需要用到Class類中的getGenericSuperclass方法
getGenericSuperclass方法的作用是:
返回該class所表示的實(shí)體(類、接口、原始類型或void)的直接父類的Type。如果父類是參數(shù)化類型(即有泛型定義),那么返回的Type對(duì)象必須準(zhǔn)確的反應(yīng)源代碼中使用的實(shí)際類型參數(shù)。
如果是帶有泛型的父類,則會(huì)返回ParameterizedType,如果當(dāng)前Class是Object類,接口,原始類型或者void,則會(huì)返回null。
如果此對(duì)象表示數(shù)組類,則返回表示Object類的Class對(duì)象。
ParameterizedType類有3個(gè)方法,其中g(shù)etActualTypeArguments能獲取到泛型列表的數(shù)組。
那么在父類中,如果要獲取子類聲明的泛型類型,就可以使用此方法
Type genericSuperclass = this.getClass().getGenericSuperclass(); if (genericSuperclass instanceof ParameterizedType){ ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } }
如此一來(lái),就可以獲取到父類的泛型了。
public abstract class TestClass<E> { public void print(){ Type genericSuperclass = this.getClass().getGenericSuperclass(); List<Type> list = null; if (genericSuperclass instanceof ParameterizedType){ ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); list = Arrays.asList(actualTypeArguments); } System.out.println(this.getClass() + " 的泛型 = " + list); } } public class TestStringClass extends TestClass<String>{ public static void main(String[] args) { TestStringClass testStringClass = new TestStringClass(); testStringClass.print(); } } // class xxx.TestStringClass 的泛型 = [class java.lang.String] public class TestMapClass extends TestClass<Map<String,String>>{ public static void main(String[] args) { TestMapClass testMapClass = new TestMapClass(); testMapClass.print(); } } // class xxx.TestMapClass 的泛型 = [java.util.Map<java.lang.String, java.lang.String>]
如果我們想獲取泛型中的泛型,例如上面的TestClass<Map<String,String>>中的Map的泛型。
我們可以看到ParameterizedType有很多實(shí)現(xiàn)類,其中java原生的實(shí)現(xiàn)類為sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
這個(gè)實(shí)現(xiàn)類中也有一個(gè)actualTypeArguments屬性,也就是說(shuō),可以繼續(xù)嘗試獲取泛型列表
獲取接口定義的泛型
很多的接口上也定義了泛型描述,可以通過(guò)Class的getGenericInterfaces方法獲取,因?yàn)橐粋€(gè)類可以實(shí)現(xiàn)多個(gè)接口,所以返回了一個(gè)Type數(shù)組,可以遍歷數(shù)組,找到需要處理的接口對(duì)應(yīng)的Type,其余的操作就獲取父類上的泛型操作一致了。
獲取屬性的泛型
獲取屬性的泛型,先通過(guò)Class,獲取到需要獲取泛型的Field,然后過(guò)個(gè)Field類的getGenericType方法獲取到Type,其余操作與獲取父類上的泛型操作一致。
通過(guò)Spring工具類獲取
spring-core工程中,提供了一個(gè)ResolvableType工具類,他可以從屬性、方法參數(shù)、方法返回、類中后去對(duì)應(yīng)的泛型。從Spring4.0開始提供這個(gè)工具類。
常用的方法有
- forField(Field field) 獲取屬性的泛型
- forMethodParameter(Method method, int parameterIndex) 獲取方法指定參數(shù)的泛型
- forMethodReturnType(Method method) 獲取方法返回值的泛型
- forConstructorParameter(Constructor constructor, int parameterIndex) 獲取構(gòu)造函數(shù)指定參數(shù)的泛型
- forClass(Class clazz) 獲取class的泛型
- forType(Type type) 獲取type的泛型
- forInstance(Object) 通過(guò)實(shí)體獲取泛型
官方示例:
private HashMap<Integer, List<String>> myMap; public void example() { ResolvableType t = ResolvableType.forField(getClass().getDeclaredField("myMap")); t.getSuperType(); // AbstractMap<Integer, List<String>> t.asMap(); // Map<Integer, List<String>> // 獲取指定下標(biāo)的泛型類型 t.getGeneric(0).resolve(); // Integer t.getGeneric(1).resolve(); // List t.getGeneric(1); // List<String> // 獲取指定下標(biāo)的泛型的指定下標(biāo)的泛型,即獲取嵌套泛型的泛型 t.resolveGeneric(1, 0); // String }
到此這篇關(guān)于Java獲取泛型實(shí)際類型的方法詳解的文章就介紹到這了,更多相關(guān)Java獲取泛型實(shí)際類型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java 中的 DataInputStream 介紹_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
DataInputStream 是數(shù)據(jù)輸入流。它繼承于FilterInputStream。接下來(lái)通過(guò)本文給大家介紹Java 中的 DataInputStream的相關(guān)知識(shí),需要的朋友參考下吧2017-05-05Java求字符串中出現(xiàn)次數(shù)最多的字符串以及出現(xiàn)次數(shù)
這篇文章主要為大家詳細(xì)介紹了Java統(tǒng)計(jì)字符串中出現(xiàn)次數(shù)最多的字符串以及出現(xiàn)次數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04解決mybatis-plus3.1.1版本使用lambda表達(dá)式查詢報(bào)錯(cuò)的方法
這篇文章主要介紹了解決mybatis-plus3.1.1版本使用lambda表達(dá)式查詢報(bào)錯(cuò)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08spring Boot與Mybatis整合優(yōu)化詳解
關(guān)于spring-boot與mybatis整合優(yōu)化方面的介紹,就是Mybatis-Spring-boot-starter的介紹,具體內(nèi)容詳情大家參考下本文2017-07-07Spring boot使用logback實(shí)現(xiàn)日志管理過(guò)程詳解
這篇文章主要介紹了Spring boot使用logback實(shí)現(xiàn)日志管理過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06Java中你絕對(duì)沒用過(guò)的一個(gè)關(guān)鍵字Record的使用
這篇文章主要給大家介紹一個(gè)?Java?中的一個(gè)關(guān)鍵字?Record,那?Record?關(guān)鍵字跟不可變類有什么關(guān)系呢?看完今天的文章你就知道了,快跟隨小編一起學(xué)習(xí)一下吧2022-11-11Spring Boot中整合Spring Security并自定義驗(yàn)證代碼實(shí)例
本篇文章主要介紹了Spring Boot中整合Spring Security并自定義驗(yàn)證代碼實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04