前言

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

泛型的使用场景

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

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

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

public interface List extends Collection {

//......}

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

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

transient Node first;

transient Node last;

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

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

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

(1)成员变量的泛型

(2)方法参数的泛型

(3)方法返回值的泛型

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

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

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

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

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

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

public class MyClass {

public List stringList = new ArrayList<>();

public List getStringList(){

return this.stringList;

}

public void setList(List list){

}

}

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

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

}

}

}

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

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

}

}

}

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

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对象,足见这个功能的强大之处,值得我们取学习,了解和使用。

java反射获取泛型_如何通过Java反射获取泛型类型信息相关推荐

  1. java 获取泛型_聊聊Java泛型擦除那些事

    >版权申明]非商业目的注明出处可自由转载 博文地址:https://blog.csdn.net/ShuSheng0007/article/details/89789849 出自:shushen ...

  2. java invoke 泛型_如何通过java反射调用含有泛型数组参数的方法

    最近在看一个算法课程,老师用的是c++的template和函数指针来完成一个实现,于是我想用java通过反射和泛型来完成,但是出现了问题. 希望通过java反射以及泛型来实现动态测试SortClass ...

  3. java创建集合有的不用泛型_为什么在Java泛型右手边的集合类型没有任何影响?...

    使用Java的Generics功能我创建了一个List对象,在左侧我使用的是原始类型List,在右侧我使用的是泛型类型ArrayList. List myList=new ArrayList(); 我 ...

  4. java中什么泛型_【原创】java中的泛型是什么,有什么作用

    泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方 ...

  5. webmagic 获取文本_学习使用Java的webmagic框架爬取网页内容

    (一)使用前的配置: 2,(1)添加依赖: us.codecraft webmagic-core 0.7.3 us.codecraft webmagic-extension 0.7.3 us.code ...

  6. java object转泛型_为什么Java的泛型要用擦除实现

    在 Java 中的 泛型 ,常常被称之为 伪泛型 ,究其原因是因为在实际代码的运行中,将实际类型参数的信息擦除掉了 (Type Erasure) .那是什么原因导致了 Java 做出这种妥协的呢?下面 ...

  7. java 反射 动态编译_动态编译java源代码和反射调用问题

    我从教程中得到了以下代码: package com.tom.labs; import java.io.IOException; import java.lang.reflect.Method; imp ...

  8. java第一阶段知识_第一阶段 Java语言(下)

    本课程是Android入门教程之Java核心技术阶段,是Java开发高级部分,安卓开发中的基础知识,讲解以下内容: (一)反射与内省 讲解了什么是反射,反射在应用中的作用,相关反射的API,如Clas ...

  9. 新手学java 学哪方面_初学者学Java应从哪些方面学习?

    原标题:初学者学Java应从哪些方面学习? Java作为应用于网络的最好语言,前景无限看好.然而,就算用Java建造一个不是很烦琐的web应用,也不是件轻松的事情.那么,初学者学Java应从哪些方面学 ...

最新文章

  1. 一文读懂云计算、边缘计算、移动边缘计算和自动驾驶的前世今生!
  2. 陆奇全面解读 AI 创业创新发展趋势,创业公司应该如何把握住机会?
  3. 如何通过网站SEO诊断来做竞争对手的分析?
  4. Windows中用运行命令直接启动指定软件的方法
  5. 「Ubuntu」Problem executing scripts APT::Update::Post-Invoke-Success ‘if /usr/bin/test -w /var/lib
  6. oracle 取mac地址,java执行命令,得到Mac地址
  7. 深入显出谈Java的发展历程及语言特点
  8. C/C++:Windows编程—Windows RPC 传递自定义数据类型、自定义数据类型数组、指针数组
  9. android:gravity与android:layout_gravity
  10. Python报错can only concatenate str (not “int“) to str
  11. Java入门学习笔记之变量与计算
  12. 智能家居(1)行业发展分析
  13. 001-前端课程介绍
  14. css实现跑马灯效果
  15. API MISUSE: <CBPeripheralManager: 0x282c00070> can only accept this command while in the powered on
  16. android 文件管理器下载,ES文件管理器下载
  17. 关于Eureka注册中心启动报错的原因
  18. 线性回归 正规方程详细推导过程
  19. MPLAB 安装 mmc 报错需要安装web相关插件
  20. 2022电工杯A题B题高质量保奖代码思路合集

热门文章

  1. android 代码循环,Android – 每5秒循环一部分代码
  2. 技术文件服务器搭建,搭建文件服务器_mob604756e49326的技术博客_51CTO博客
  3. android 滑动缩放监听,基于Android的ViewPager动画特效实现页面左右滑动效果(实现缩放...
  4. MIPS架构之start.s汇编分析
  5. static_cast, dynamic_cast, const_cast,reinterpret_cast探讨
  6. 图像变换——分段线性变换
  7. Anders Hejlsberg语录
  8. tf.read_file和tf.image.decode_jpeg处理图片(转)
  9. 周末计划-20171028
  10. 【贪心算法】POJ-2376 区间问题