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


前言
关于Java泛型,很多人都有一个误解,认为Java代码在编译时会擦除泛型的类型,从而在运行时导致没法访问其类型,这其实并不完全正确,因为有一部分泛型信息是可以在运行时动态获取的,这部分信息基本能够满足我们日常开发中的大多数场景,本篇文章我们就来了解相关的知识。
泛型的使用场景
在讨论如何用反射获取泛型类型之前,我们先来回顾下,在Java里面什么时候会使用泛型,了解这个问题之后,我们才能继续思考如何用反射获取泛型类型。
在Java里面使用泛型通用会应用在两个场景:
(1)声明一个类或者接口时使用泛型 比如,Java里面的List接口,其定义如下:
public interface List<E> extends Collection<E> {//......}
(2)在类里面使用一个泛型类
比如在Java的LinkedList的源码中,有两个成员变量定义如下,分别代表链表的头和尾:
transient Node<E> first; transient Node<E> last;
ok,在上面的两种场景中,第一种场景在类和接口上声明的泛型,在运行时反射该类,是没法知道其参数信息的,包括对象本身也不知道它的泛型是什么。
但类似第二种场景中通过对象的指针引用,我们是可以通过反射获取其泛型的类型信息的,但要注意局部变量是没法获取其泛型信息的。
在Java里面可以通过反射获取泛型信息的场景有三个,分别是:
(1)成员变量的泛型
(2)方法参数的泛型
(3)方法返回值的泛型
注意,通过对象本身也是没法获取的。
不能通过发射获取泛型类型信息的场景有二个,分别是:
(1)类或接口声明的泛型信息
(2)局部变量的泛型信息
获取方法返回值的泛型类型
如下面定义的一个测试类:
public class MyClass {
public List<String> stringList = new ArrayList<>();
public List<String> getStringList(){ return this.stringList; }
public void setList(List<Integer> list){
}
获取getStringList方法返回值的泛型类型信息的代码如下:
public static void getMethodReturnType() throws Exception{