java通过反射获取泛型类型信息(代码片段)

二木成林 二木成林     2022-12-20     143

关键词:

概述

通常泛型在如下几种情况下使用:

  • 含有泛型的类
// 格式
修饰符 class 类名<代表泛型的变量>  

// 实例
public class ArrayList<E> 
    public boolean add(E e) 

    public E get(int index) 
  • 含有泛型的方法
// 格式
修饰符 <代表泛型的变量> 返回值类型 方法参数(参数)  

// 实例
public class MyGenericClass 
    public <ABC> void print(ABC abc) 
        System.out.println(abc);
    
  • 含有泛型的接口
// 格式
修饰符 interface 接口名<代表泛型的变量>  

// 实例
public interface MyGenericInterface<E> 
    public abstract void add(E e);

    public abstract E getE();

泛型的使用场景就是如上三种,当在类或接口中定义了泛型后,就可以在类或接口中的成员变量、方法参数、方法返回值中也使用泛型;当定义了含有泛型的方法后,就可以在该方法的方法参数、方法返回值和方法内局部变量中使用泛型。

反射获取泛型的场景

在Java中可以通过反射获取泛型信息的场景有如下三个:

  • (1)成员变量的泛型
  • (2)方法参数的泛型
  • (3)方法返回值的泛型

在Java中不可以通过反射获取泛型信息的场景有如下两个:

  • (1)类或接口声明的泛型
  • (2)局部变量的泛型

实例

我们先创建一个类,该类中正好有含有泛型的成员变量、含有泛型的方法返回值、含有泛型的方法参数。代码如下:

class MyClass 
    // 带有泛型的成员变量
    public List<Object> list = new ArrayList<>();

    // 方法返回值中带有泛型
    public List<Object> getList() 
        return list;
    

    // 方法参数带有泛型
    public void setList(List<Object> list) 
        this.list = list;
    

要获取泛型信息,必须要注意ParameterizedType类,该类中的getActualTypeArguments()方法可以有效获取泛型信息。

具体的实例代码如下:

public class Demo 
    public static void main(String[] args) throws NoSuchMethodException, NoSuchFieldException 
        // 获取成员方法返回值的泛型类型信息
        getMethodReturnValueGeneric();

        System.out.println("======================================");

        // 获取成员变量的泛型类型信息
        getMemberVariablesGeneric();

        System.out.println("======================================");

        // 获取成员方法参数的泛型类型信息
        getMethodParametricGeneric();
    

    /**
     * 获取方法返回值的泛型类型信息
     *
     * @throws NoSuchMethodException
     */
    public static void getMethodReturnValueGeneric() throws NoSuchMethodException 
        // 获取名为"getList"的方法,在MyClass类中
        Method getListMethod = MyClass.class.getMethod("getList");
        // 获取返回值类型,getGenericReturnType()会返回值带有泛型的返回值类型
        Type genericReturnType = getListMethod.getGenericReturnType();
        // 但我们实际上需要获取返回值类型中的泛型信息,所以要进一步判断,即判断获取的返回值类型是否是参数化类型ParameterizedType
        if (genericReturnType instanceof ParameterizedType) 
            // 如果要使用ParameterizedType中的方法,必须先强制向下转型
            ParameterizedType type = (ParameterizedType) genericReturnType;
            // 获取返回值类型中的泛型类型,因为可能有多个泛型类型,所以返回一个数组
            Type[] actualTypeArguments = type.getActualTypeArguments();
            // 循环数组,遍历每一个泛型类型
            for (Type actualTypeArgument : actualTypeArguments) 
                Class typeArgClass = (Class) actualTypeArgument;
                System.out.println("成员方法返回值的泛型信息:" + typeArgClass);
            
        
    

    /**
     * 获取类中成员变量的泛型类型信息
     *
     * @throws NoSuchFieldException
     */
    public static void getMemberVariablesGeneric() throws NoSuchFieldException 
        // 获取MyTestClass类中名为"list"的字段
        Field listField = MyClass.class.getField("list");
        // 获取该字段的类型信息,getGenericType()方法能够获取带有泛型的类型信息
        Type genericType = listField.getGenericType();
        // 但我们实际上需要获取返回值类型中的泛型信息,所以要进一步判断,即判断获取的返回值类型是否是参数化类型ParameterizedType
        if (genericType instanceof ParameterizedType) 
            ParameterizedType parameterizedType = (ParameterizedType) genericType;
            // 获取成员变量的泛型类型信息
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) 
                Class fieldArgClass = (Class) actualTypeArgument;
                System.out.println("成员变量的泛型信息:" + fieldArgClass);
            
        
    

    /**
     * 获取方法参数的泛型类型信息
     *
     * @throws NoSuchMethodException
     */
    public static void getMethodParametricGeneric() throws NoSuchMethodException 
        // 获取MyTestClass类中名为"setList"的方法
        Method setListMethod = MyClass.class.getMethod("setList", List.class);
        // 获取该方法的参数类型信息(带有泛型)
        Type[] genericParameterTypes = setListMethod.getGenericParameterTypes();
        // 但我们实际上需要获取返回值类型中的泛型信息,所以要进一步判断,即判断获取的返回值类型是否是参数化类型ParameterizedType
        for (Type genericParameterType : genericParameterTypes) 
            ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
            // 获取成员方法参数的泛型类型信息
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) 
                Class realType = (Class) actualTypeArgument;
                System.out.println("成员方法参数的泛型信息:" + realType);
            
        
    

/*打印结果:
    成员方法返回值的泛型信息:class java.lang.Object
    ======================================
    成员变量的泛型信息:class java.lang.Object
    ======================================
    成员方法参数的泛型信息:class java.lang.Object
 */

反射获取泛型信息(代码片段)

获取泛型信息反射操作泛型代码练习importcom.exception.demo01.Test;importjava.lang.reflect.Method;importjava.lang.reflect.ParameterizedType;importjava.lang.reflect.Type;importjava.util.List;importjava.util.Map;//通过反射获取泛 查看详情

180530-反射获取泛型类的实际参数(代码片段)

文章链接:https://liuyueyi.github.io/hexblog/2018/05/30/180530-通过反射获取泛型类的实际参数/反射获取泛型类的实际参数泛型用得还是比较多的,那么如何获取泛型类上实际的参数类型呢?比如一个接口为publicinterfaceIBolt<T,K>现在给... 查看详情

java泛型参数具体类型获取泛型返回具体类型获取(代码片段)

...前的应用都使用了泛型。有的框架如mybatis和spring都需要反射获取类型,以使得序列化和反序列化得以实现,但有时候我们根据项目的需要获取这些具体类型。比如,mybatis orm环境下,数据库字段类型和java类型不... 查看详情

31反射(获取class实例剖析运行时类的完整结构读取properties文件反射创建类越过泛型检查)枚举(代码片段)

...使用反射1、Java反射机制概述反射机制允许程序在执行期通过ReflectionAPI取得任何类的内部信息,并能直接操作任何对象的内部属性和方法;加载完类后,在方法区中就产生了一个Class类型的 查看详情

java筑基.泛型,反射,注解-利用注解加反射练习(代码片段)

...变量限定类型变量通配符泛型注解元注解注解的应用场景反射:注解+反射练习泛型:把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型泛型类/*1:把泛型定义在类上2:类型变量定义在类上,方法中也可以使... 查看详情

10.go语言反射(代码片段)

...息。其它语言中的反射C/C++语言没有支持反射功能,只能通过typeid提供非常弱化的程序运行时类型信息。Java、C#等语言都支持完整的反射功能。Lua、JavaScript类动态语言,由于其本身的语法特性就可以让代码在运行期访问程序自身... 查看详情

类型信息(rtti和反射)——反射(代码片段)

...:传统的RTTI,以及反射。下面就来说说反射。重点说说通过反射获取方法以及调用方法,即类方法提取器。1、反射:  如果你不知道一个对象的确定类型,RTTI可以告诉你。但是有个限制:这个类型在编译期间必须已知,才能... 查看详情

泛型中的类型擦除(代码片段)

通过反射理解泛型的本质(类型擦除)Java中的泛型是通过类型擦除来实现的。所谓类型擦除,是指通过类型参数合并,将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节... 查看详情

详解c#特性和反射(代码片段)

...类型信息(Type Information)用来表示类型声明的信息,通过抽象基类System.Type的实例存储这些信息,当使用反射时,CLR获取指定类型的Type对象,通过这个对象即可访问该类型的任何信息,是反射的核心用法;有以下几种方式获... 查看详情

通过反射获取泛型信息

  1packagecom.coscon.reflectionTest;23importjava.lang.reflect.Method;4importjava.lang.reflect.ParameterizedType;5importjava.lang.reflect.Type;6importjava.util.List;7importjava.util.Map;89//用 查看详情

java笔记-通过反射获取枚举类型中所有数据(代码片段)

程序运行截图如下:代码如下:Em.javapackagecn.it1995;publicenumEmONE(1,"第一个枚举"),TWO(2,"第二个枚举"),THREE(3,"第三个枚举"),FOUR(4,"第四个枚举");privateIntegerid;privateStringdescribe;E 查看详情

go基础面向对象和反射机制(代码片段)

...对象1.面向对象的概念2.构造函数3.继承与重写4.泛型二、反射1.反射介绍2.反射的基础数据类型3.反射API3.1reflect.Type①如何得到Type②指针Type转为非指针Type③获取struct成员变量的信息④获取struct成员方法的信息⑤获取函数的信息⑥... 查看详情

注解与反射-复习(代码片段)

...过程ClassLoader反射获取运行时类的结构信息动态创建对象通过反射创建对象(一般情况)通过"构造器对象"创建对象(不存在无参构造)通过反射调用成员:methodfield测试:性能分析反射获取泛型数据反射获取注解数据基于B站秦疆老师的... 查看详情

java反射编程(上)(代码片段)

文章目录反射的泛型就是用`?`来描述反射与类的操作(取得父类信息)取得父类信息1.获得本类的包名称:2.取得父类的Class对象3.取得父类接口案例:使用上述方法反射与类的操作(反射调用构造)反射调用构造1.取得指定参数类型... 查看详情

《java架构筑基》从java基础讲起——泛型与反射

通过反射获得泛型的实际类型参数把泛型变量当成方法的参数,利用Method类的getGenericParameterTypes方法来获取泛型的实际类型参数例子:publicclassGenericTest{publicstaticvoidmain(String[]args)throwsException{getParamType();}/*利用反射获取方法参数... 查看详情

java怎么获取list泛型里的对象类型

获取java泛型中的对象类型,可以参考如下代码:/***通过反射取到List中T的类型*@paramclazz*@paramfield*@return*/publicstaticClass参考技术Alist.get(0).getClass().getName() 查看详情

泛型与反射:type接口来历及子接口(代码片段)

...时候,只有原始类型。此时,所有的原始类型都通过字节码文件类Class类进行抽象。Class类的一个具体对象就代表一个指定的原始类型。泛型出现之后的类型泛型是对类的抽象,泛型出现之后,扩充了数据类型。从... 查看详情

java反射基础知识反射应用实践

Java除了给我们提供在编译期得到类的各种信息之外,还通过反射让我们可以在运行期间得到类的各种信息。通过反射获取类的信息,得到类的信息之后,就可以获取以下相关内容:Class对象构造器变量方法私有变量与私有方法注... 查看详情