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
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值