通過反射獲得泛型實際型別
阿新 • • 發佈:2019-01-03
通過反射獲得泛型實際型別
1.獲得類的泛型
子類繼承泛型父類,並對泛型進行指定,通過反射獲得指定型別,
1.使用getGenericSuperclass()方法獲得泛型父類
2.判斷是不是引數化型別是的話強轉型別為ParameterizedType
3.使用ParameterizedType的方法getActualTypeArguments()獲得泛型實際型別
程式碼如下
public class Demo1<T> {
public void study(Map<String, Integer> map, T t,String str){
}
/*
* 繼承泛型父類並指定String型別
* */
public class Demo2 extends Demo1<String>{
}
public static void main(String[] args) {
Demo1.Demo2 demo = new Demo1<>().new Demo2 ();
//獲得帶有泛型的父類
Type genericSuperclass = demo.getClass().getGenericSuperclass();
//判斷父類是不是引數化的型別,如果是強轉成ParameterizedType
if (genericSuperclass instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType)genericSuperclass;
//獲得Demo1<String>,<>中的實際型別引數
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
//獲得引數型別
Class<?> clazz = (Class<?>)actualTypeArguments[0];
System.out.println(clazz);
}
}
}
結果:
2.獲得方法引數中的泛型實際型別
方法引數使用了帶有泛型的類如Map<K,V>,獲得泛型的實際型別,程式碼如下:
1.反射獲得對應方法
2.呼叫getGenericParameterTypes()方法獲得方法引數型別集合
3.遍歷集合對ParameterizedType型別引數進行操作
4.使用ParameterizedType的方法getActualTypeArguments()獲得泛型實際型別
public class Demo {
//一個方法有Map型別和List型別的引數,並指定泛型
public void study(Map<String, Integer> map, List<String> list){
}
public static void main(String[] args) {
try {
//通過反射獲得該方法
Method study = Demo.class.getMethod("study", Map.class, List.class);
//獲得該方法的所有引數型別
Type[] genericParameterTypes = study.getGenericParameterTypes();
for (Type type : genericParameterTypes){
System.out.println("##"+ type);
//如果引數為引數化的型別進行強轉
if (type instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType)type;
//獲得引數化型別中實際引數(Map<String, Integer> 中<>內定義的引數)
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
//遍歷輸出
for (Type tt : actualTypeArguments){
System.out.println(tt);
}
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
執行結果
3.獲得方法返回值中的泛型實際型別
使用getGenericReturnType()方法獲得方法返回值型別,之後的操作和獲得引數返回型別方法類似
public class Demo2 {
//一個方法的返回型別是Map並指定了泛型型別
public Map<String, Integer> study(){
return new HashMap<String,Integer>();
}
public static void main(String[] args) {
try {
//通過反射獲得該方法
Method study = Demo2.class.getMethod("study");
//獲得方法的返回型別
Type genericReturnType = study.getGenericReturnType();
System.out.println("###" + genericReturnType);
////如果返回值型別為引數化的型別進行強轉
if (genericReturnType instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType)genericReturnType;
//獲得引數化型別中實際引數(Map<String, Integer> 中<>內定義的引數)
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
//遍歷輸出
for (Type type : actualTypeArguments){
System.out.println(type);
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
執行結果
4.獲得萬用字元型別的上下界
先按照獲得引數泛型實際型別的方法獲得萬用字元表示式(? extends T 或?super T),再進行後續操作。
使用WildcardType介面的getUpperBounds()和getLowerBounds()來獲得型別的上下界
public class Demo3 {
//study方法傳入List類似引數,其中List指定型別上界為Demo3
public void study(List<? extends Demo3> list){
}
public static void main(String[] args) {
try {
Method study = Demo3.class.getMethod("study", List.class);
Type[] genericParameterTypes = study.getGenericParameterTypes();
//獲得List引數(java.util.List<? extends com.fxl.GenenricReflect.Demo3>)
Type type = genericParameterTypes[0];
if (type instanceof ParameterizedType){
System.out.println(type);
//獲得List引數中的泛型實際型別(? extends com.fxl.GenenricReflect.Demo3)
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
for (Type mytypes : actualTypeArguments){
//判斷是不是WildcardType並強轉
if (mytypes instanceof WildcardType){
WildcardType wt = (WildcardType)mytypes;
//獲得型別的上界(class com.fxl.GenenricReflect.Demo3)
Type[] upperBounds = wt.getUpperBounds();
System.out.println(upperBounds[0]);
}
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
執行結果
個人筆記,如有錯誤還望指出