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获取泛型实际类型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

最新评论