1. 程式人生 > >Spring 通過 ResolvableType來獲取泛型

Spring 通過 ResolvableType來獲取泛型

由於泛型擦除,使得Generic無法獲取自己的Generic的Type型別。實際上BadClass()例項化以後Class裡面就不包括T的資訊了,對於Class而言T已經被擦拭為Object,而真正的T引數被轉到使用T的方法(或者變數宣告或者其它使用T的地方)裡面(如果沒有那就沒有存根),所以無法反射到T的具體類別,也就無法得到T.class。 而getGenericSuperclass()是Generic繼承的特例,對於這種情況子類會儲存父類的Generic引數型別,返回一個ParameterizedType,這時可以獲取到父類的T.class了,這也正是子類確定應該繼承什麼T的方法

傳統Java方式獲取泛型資訊

繼承的父類是泛型(class.getGenericSuperclass())

  • 用到的類

    public class Person<T> {
    
    }
    public class Student extends Person<String> {
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 測試程式碼
@Test
public void test01() {
    // 對於繼承的父類是泛型的情況
    ParameterizedType genericSuperclass = (ParameterizedType) Student.class.getGenericSuperclass();
    System.out
.println(genericSuperclass); Type type = genericSuperclass.getActualTypeArguments()[0]; System.out.println(type); System.out.println(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 執行結果
com.fanxing.Person<java.lang.String>
class java.lang.String
  • 1
  • 2

實現的介面是泛型

  • 用到的類

    public interface IDAO<T> {
    
    }
    public class StringDao  implements
    IDAO<String>{
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 測試程式碼
@Test
public void test02() {
    // 對於實現的介面是泛型的處理情況
    ParameterizedType parameterizedType = (ParameterizedType) StringDao.class.getGenericInterfaces()[0];
    System.out.println(parameterizedType);
    Type genericType = parameterizedType.getActualTypeArguments()[0];
    System.out.println(genericType);
    System.out.println();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 執行結果
com.fanxing.IDAO<java.lang.String>
class java.lang.String
  • 1
  • 2

使用Spring的ResolvableType獲取泛型資訊

繼承的父類是泛型

  • 測試程式碼
@Test
public void test04() {
    // Spring的提供工具類,用於獲取繼承的父類是泛型的資訊
    ResolvableType resolvableType = ResolvableType.forClass(Student.class);
    System.out.println(resolvableType);
    Class<?> resolve = resolvableType.getSuperType().getGeneric(0).resolve();
    System.out.println(resolve);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 執行結果
com.fanxing.Student
class java.lang.String
  • 1
  • 2

實現的介面是泛型

  • 測試程式碼
@Test
public void test03() {
    // Spring的提供工具類,用於獲取實現的介面是泛型的資訊
    ResolvableType resolvableType = ResolvableType.forClass(StringDao.class);
    System.out.println(resolvableType);
    Class<?> resolve = resolvableType.getInterfaces()[0].getGeneric(0).resolve();
    System.out.println(resolve);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 執行結果
com.fanxing.StringDao
class java.lang.String
  • 1
  • 2

得到欄位級別的泛型資訊

用到的Java類
package com.fanxing;

import java.util.List;
import java.util.Map;

public class GenericClass {

    private List<String> listString;
    private List<List<String>> listLists;
    private Map<String, Long> maps;
    private Person<String> persons;

    public GenericClass() {
    }

    public List<String> getListString() {
        return listString;
    }

    public void setListString(List<String> listString) {
        this.listString = listString;
    }

    public Map<String, Long> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Long> maps) {
        this.maps = maps;
    }

    public Person<String> getPersons() {
        return persons;
    }

    public void setPersons(Person<String> persons) {
        this.persons = persons;
    }

    public List<List<String>> getListLists() {
        return listLists;
    }

    public void setListLists(List<List<String>> listLists) {
        this.listLists = listLists;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
自定義的泛型資訊
  • 測試程式碼
// Spring的提供工具類,用於欄位的泛型資訊,Person<String>
ResolvableType resolvableType = ResolvableType.forField(ReflectionUtils.findField(GenericClass.class, "persons"));
System.out.println(resolvableType);
// 然後通過如下API得到Person<String>的第0個位置上的泛型實參型別,即String
Class<?> resolve = resolvableType.getGeneric(0).resolve();
System.out.println(resolve);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 輸出結果
com.fanxing.Person<java.lang.String>
class java.lang.String
  • 1
  • 2
  • 3
獲取List屬性的泛型
List< String >的情況
  • 測試程式碼
ResolvableType resolvableType = ResolvableType.forField(ReflectionUtils.findField(GenericClass.class, "listString"));
System.out.println(resolvableType);
// 然後通過如下API得到Person<String>的第0個位置上的泛型實參型別,即String
Class<?> resolve = resolvableType.getGeneric(0).resolve();
System.out.println(resolve);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 執行結果
java.util.List<java.lang.String>
class java.lang.String
  • 1
  • 2
List< List < String > > 的情況
  • 測試程式碼
@Test
public void test07() {
    // Spring的提供工具類,用於欄位的泛型資訊,List<List<String>>
    ResolvableType resolvableType = ResolvableType.forField(ReflectionUtils.findField(GenericClass.class, "listLists"));
    System.out.println(resolvableType);
    // 然後通過如下API得到Person<String>的第0個位置上的泛型實參型別,即String
    // Class<?> resolve =
    // resolvableType.getGeneric(0).getGeneric(0).resolve();
    Class<?> resolve = resolvableType.getGeneric(0, 0).resolve();
    System.out.println(resolve);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 輸出結果
java.util.List<java.util.List<java.lang.String>>
class java.lang.String
  • 1
  • 2
  • 3
獲取Map屬性的泛型
  • 測試程式碼
@Test
    public void test08() {
        // Spring的提供工具類,用於欄位的泛型資訊,List<List<String>>
        ResolvableType resolvableType = ResolvableType//
                .forField(ReflectionUtils.findField(GenericClass.class, "maps"));
        System.out.println(resolvableType);
        // 然後通過如下API得到Person<String>的第0個位置上的泛型實參型別,即String
        Class<?> resolve = resolvableType.getGeneric(0).resolve();
        System.out.println(resolve);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 執行結果
java.util.Map<java.lang.String, java.lang.Long>
class java.lang.String
  • 1
  • 2

得到方法返回值的泛型資訊

  • 測試程式碼
@Test
    public void test09() {
        // Spring的提供工具類,用於方法的返回值的泛型資訊,Map<String, Long>
        ResolvableType resolvableType = ResolvableType.forMethodReturnType(ReflectionUtils.findMethod(GenericClass.class, "getMaps"));
        Class<?> resolve = resolvableType.getGeneric(1).resolve();
        System.out.println(resolve);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 執行結果
@Test
    public void test09() {
        // Spring的提供工具類,用於方法的返回值的泛型資訊,Map<String, Long>
        ResolvableType resolvableType = ResolvableType.forMethodReturnType(ReflectionUtils.findMethod(GenericClass.class, "getMaps"));
        Class<?> resolve = resolvableType.getGeneric(1).resolve();
        System.out.println(resolve);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

參考的部落格地址

http://jinnianshilongnian.iteye.com/blog/1993608