Java获取泛型实际类型的方法详解

 更新时间:2023年11月06日 09:54:09   作者:杨小胖要减肥  
这篇文章主要介绍了Java获取泛型实际类型的方法详解,泛型,即“参数化类型”,一提到参数,最熟悉的就是定义方法时有形参列表,普通方法的形参列表中,每个形参的数据类型是确定的,而变量是一个参数,需要的朋友可以参考下

Java反射获取

获取类上的泛型

获取父类定义的泛型

例如现在有一个父类

public abstract class TestClass<E> {
  ......
}

同时他有多个实现类,如

public class TestStringClass extends TestClass<String>{
  ....
}

public class TestIntegerClass extends TestClass<Integer>{
  ....
}
....

此时如果要获取该类上声明的泛型

需要用到Class类中的getGenericSuperclass方法

getGenericSuperclass方法的作用是:

返回该class所表示的实体(类、接口、原始类型或void)的直接父类的Type。如果父类是参数化类型(即有泛型定义),那么返回的Type对象必须准确的反应源代码中使用的实际类型参数。

如果是带有泛型的父类,则会返回ParameterizedType,如果当前Class是Object类,接口,原始类型或者void,则会返回null。

如果此对象表示数组类,则返回表示Object类的Class对象。

ParameterizedType类有3个方法,其中getActualTypeArguments能获取到泛型列表的数组。

那么在父类中,如果要获取子类声明的泛型类型,就可以使用此方法

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);
  }
}

如此一来,就可以获取到父类的泛型了。

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有很多实现类,其中java原生的实现类为sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl

这个实现类中也有一个actualTypeArguments属性,也就是说,可以继续尝试获取泛型列表

获取接口定义的泛型

很多的接口上也定义了泛型描述,可以通过Class的getGenericInterfaces方法获取,因为一个类可以实现多个接口,所以返回了一个Type数组,可以遍历数组,找到需要处理的接口对应的Type,其余的操作就获取父类上的泛型操作一致了。

获取属性的泛型

获取属性的泛型,先通过Class,获取到需要获取泛型的Field,然后过个Field类的getGenericType方法获取到Type,其余操作与获取父类上的泛型操作一致。

通过Spring工具类获取

spring-core工程中,提供了一个ResolvableType工具类,他可以从属性、方法参数、方法返回、类中后去对应的泛型。从Spring4.0开始提供这个工具类。

常用的方法有

  • forField(Field field) 获取属性的泛型
  • forMethodParameter(Method method, int parameterIndex) 获取方法指定参数的泛型
  • forMethodReturnType(Method method) 获取方法返回值的泛型
  • forConstructorParameter(Constructor constructor, int parameterIndex) 获取构造函数指定参数的泛型
  • forClass(Class clazz) 获取class的泛型
  • forType(Type type) 获取type的泛型
  • forInstance(Object) 通过实体获取泛型

官方示例:

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>>
    	// 获取指定下标的泛型类型
      t.getGeneric(0).resolve(); // Integer
      t.getGeneric(1).resolve(); // List
      t.getGeneric(1); // List<String>
    	// 获取指定下标的泛型的指定下标的泛型,即获取嵌套泛型的泛型
      t.resolveGeneric(1, 0); // String
  }

到此这篇关于Java获取泛型实际类型的方法详解的文章就介绍到这了,更多相关Java获取泛型实际类型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • spring boot整合redis主从sentinel方式

    spring boot整合redis主从sentinel方式

    这篇文章主要介绍了spring boot整合redis主从sentinel方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • JavaFx实现登录成功跳转到程序主页面

    JavaFx实现登录成功跳转到程序主页面

    这篇文章主要为大家详细介绍了JavaFx实现登录成功跳转到程序主页面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • java swing实现的扫雷游戏及改进版完整示例

    java swing实现的扫雷游戏及改进版完整示例

    这篇文章主要介绍了java swing实现的扫雷游戏及改进版,结合完整实例形式对比分析了java使用swing框架实现扫雷游戏功能与相关操作技巧,需要的朋友可以参考下
    2017-12-12
  • 浅谈java中字节与字符的区别

    浅谈java中字节与字符的区别

    这篇文章主要介绍了浅谈java中字节与字符的区别,字节是java中的基本数据类型,用来申明字节型的变量;字符是语义上的单位,它是有编码的,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • 详解如何在springcloud分布式系统中实现分布式锁

    详解如何在springcloud分布式系统中实现分布式锁

    最近在看分布式锁的资料,本文就介绍一下利用springcloud结合redis实现分布式锁,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • Hibernate一级缓存和二级缓存详解

    Hibernate一级缓存和二级缓存详解

    今天小编就为大家分享一篇关于Hibernate一级缓存和二级缓存详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • 详解Mybatis拦截器安全加解密MySQL数据实战

    详解Mybatis拦截器安全加解密MySQL数据实战

    本文主要介绍了Mybatis拦截器安全加解密MySQL数据实战,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • java制作复制文件工具代码分享

    java制作复制文件工具代码分享

    如果目标位置没有同名文件,则直接拷贝过去;如果目标位置已有同名文件,则比对文件的最后修改日期,来进行覆盖或者忽略。程序会在可以在复制过程中自动创建目录,并生成log文件,创建了哪些目录、文件,覆盖了哪些文件、跳过了哪些文件,文件的时间、位置等信息都一目了然
    2014-01-01
  • RabbitMQ消息拒绝如何解决

    RabbitMQ消息拒绝如何解决

    这篇文章主要介绍了RabbitMQ消息拒绝如何解决问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Java String类和StringBuffer类的区别介绍

    Java String类和StringBuffer类的区别介绍

    这篇文章主要介绍了Java String类和StringBuffer类的区别, 关于java的字符串处理我们一般使用String类和StringBuffer类有什么不同呢,下面我们一起来看看详细介绍吧
    2022-03-03

最新评论