前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何通过Java反射获取泛型类型信息

如何通过Java反射获取泛型类型信息

作者头像
我是攻城师
发布2019-06-17 16:00:39
8.9K0
发布2019-06-17 16:00:39
举报
文章被收录于专栏:我是攻城师我是攻城师

前言

关于Java泛型,很多人都有一个误解,认为Java代码在编译时会擦除泛型的类型,从而在运行时导致没法访问其类型,这其实并不完全正确,因为有一部分泛型信息是可以在运行时动态获取的,这部分信息基本能够满足我们日常开发中的大多数场景,本篇文章我们就来了解相关的知识。

泛型的使用场景

在讨论如何用反射获取泛型类型之前,我们先来回顾下,在Java里面什么时候会使用泛型,了解这个问题之后,我们才能继续思考如何用反射获取泛型类型。

在Java里面使用泛型通用会应用在两个场景:

(1)声明一个类或者接口时使用泛型 比如,Java里面的List接口,其定义如下:

代码语言:javascript
复制
public interface List<E> extends Collection<E> {//......}

(2)在类里面使用一个泛型类

比如在Java的LinkedList的源码中,有两个成员变量定义如下,分别代表链表的头和尾:

代码语言:javascript
复制
    transient Node<E> first;    transient Node<E> last;

ok,在上面的两种场景中,第一种场景在类和接口上声明的泛型,在运行时反射该类,是没法知道其参数信息的,包括对象本身也不知道它的泛型是什么。

但类似第二种场景中通过对象的指针引用,我们是可以通过反射获取其泛型的类型信息的,但要注意局部变量是没法获取其泛型信息的。

在Java里面可以通过反射获取泛型信息的场景有三个,分别是:

(1)成员变量的泛型

(2)方法参数的泛型

(3)方法返回值的泛型

注意,通过对象本身也是没法获取的。

不能通过发射获取泛型类型信息的场景有二个,分别是:

(1)类或接口声明的泛型信息

(2)局部变量的泛型信息

获取方法返回值的泛型类型

如下面定义的一个测试类:

代码语言:javascript
复制
public class MyClass {
    public List<String> stringList = new ArrayList<>();


    public List<String> getStringList(){        return this.stringList;    }

    public void setList(List<Integer> list){
    }
    }

获取getStringList方法返回值的泛型类型信息的代码如下:

代码语言:javascript
复制
public static void  getMethodReturnType() throws Exception{
    Method method=MyClass.class.getMethod("getStringList",null);    System.out.println(method.getReturnType());    Type retrunType=method.getGenericReturnType();    System.out.println(retrunType);    if(retrunType instanceof ParameterizedType){        ParameterizedType type=(ParameterizedType)retrunType;        Type[] typeArguments=type.getActualTypeArguments();        for(Type typeArgument:typeArguments){            Class typeArgClass=(Class)typeArgument;
            System.out.println("泛型类型:"+typeArgClass);        }    }
}

获取成员变量的泛型类型信息

代码语言:javascript
复制
   public static void getGenericFieldTypes()throws Exception{
        Field field=MyClass.class.getField("stringList");        Type genericsFieldType=field.getGenericType();        if(genericsFieldType instanceof ParameterizedType){            ParameterizedType parameterizedType=(ParameterizedType) genericsFieldType;            Type[] fieldArgTypes=parameterizedType.getActualTypeArguments();            for (Type fieldArgType:fieldArgTypes){                Class fieldArgClass=(Class) fieldArgType;                System.out.println("泛型字段的类型:"+fieldArgClass);            }        }
    }

获取方法参数的泛型类型信息

代码语言:javascript
复制
    public static void getMethodParameterTypes() throws Exception{        Method method=MyClass.class.getMethod("setList",List.class);        Type[] genericParameterTypes=method.getGenericParameterTypes();        for (Type genericType:genericParameterTypes){            if(genericType instanceof ParameterizedType){                ParameterizedType parameterizedType=(ParameterizedType)genericType;               Type[] types= parameterizedType.getActualTypeArguments();               for (Type type:types){                   Class realType=(Class) type;                   System.out.println("方法参数的类型:"+realType);               }            }        }
    }

总结

本文主要介绍了如何使用反射来获取部分泛型参数的类型信息,并介绍了那些场景不能使用反射获取其类型信息,通过反射获取参数的类型的泛型信息其实是非常有用的一个功能,比如在一些json工具的开源包里面,可以对Java里面泛型的各种List,List等类型做正确识别,其实就是利用反射的这个功能,从而让解析代码具有更强的通用型,可以将对象转成字符串json,也可以从字符串中恢复成bean对象,足见这个功能的强大之处,值得我们取学习,了解和使用。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 我是攻城师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 泛型的使用场景
  • 获取方法返回值的泛型类型
  • 获取成员变量的泛型类型信息
  • 获取方法参数的泛型类型信息
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档