avatar

Catalog
反射

预备知识

动态语言和静态语言

  • 动态语言
    • 是一种可以在运行时改变其结构的语言,例如新的函数、对象、甚至代码可以在运行时被引进,已有的函数可以被删除或是 其他结构上的变化。通俗的讲就是在运行时代码可以根据某些条件改变自身结构
    • 举例:Object-C、C#、JavaScript、PHP、Python
  • 静态语言
    • 与动态语言相对的,运行时结构不可改变的语言
    • C、C++、JAVA
  • java不是动态语言,但通过反射机制实现类似动态语言的特性

Class对象

获取Class对象

  • 通过类名获得: 类名.class , 最高效

  • 通过对象获得: 对象.getClass()

  • 通过forname获得 :Class.forName(" ")
  • 通过内置类型的包装类获得:内置类型包装类.TYPE
  • 已知一个Class,获取其获得父类Class:Class.getSuperclass()

哪些类型可以有Class对象

  • 接口
  • 数组(同一维度的数组是同一个Class对象,不同维度的数组是不同的Class对象)
  • 注解
  • 枚举
  • 基本数据类型
  • void
  • Class

QQ截图20200331110904

QQ截图20200331110935

使用反射

反射操作Class对象

JVM在第一次读取到一中class类型时,就将其加载入内存。每加载一种class,JVM就为其创建一个Class类型的实例,并关联起来。这个Class实例是在JVM内部创建的,构造方法是private,只有JVM能创建Class实例,我们自己的JAVA程序无法创建。

通过引入import java.lang.reflect.Field;可以通过Field获取一个类的字段,进而通过getset方法获取和修改对象的字段值

通过引入import java.lang.reflect.Method;可以通过Method获取一个类的方法,进而通过invoke调用方法

通过引入import java.lang.reflect.Constructor;可以通过Constructor获取一个类的构造方法,进而通过newInstance()方法构造一个类的实例(也可以在获取Class的newInstance方法,但是这样做只能调用无参构造方法).

我们还可以通过getSuperclass()获取一个类的父类,通过getInterfaces()获取一个类的接口,

反射操作泛型

为了反射操作泛型,JAVA新增了几种类型

  • ParameterizedType :表示一种参数化类型,比如Collection
  • GenericArrayType :表示一种元素类型时参数化类型或者类型变量的数组类型
  • TypeVariable:是各种类型变量的通用父接口
  • WildcardType:代表一种通配符类型表达式

QQ截图20200401231916

如图所示:

test01是一个以泛型为参数的方法,当我们对test01使用method.getGenericParameterTypes() 方法时,只能得到Map 和List (这两个就是ParameterizedType类型),而无法获得尖括号里面的Object,为此,我们还需要对其使用getActualTypeArguments()方法。

以上就是泛型作为函数参数时通过反射获取的方法,当泛型作为函数返回值时,我们只需要将method.getGenericParameterTypes() 换成method.getGenericReturnTypes() 即可。

反射操作注解

  • 获取一个类的全部注解: getAnnotations()

  • 获取指定注解 :getAnnotation(注解.class)

获取注解后,可以进一步通过 “.字段”来获取注解的字段值

Author: realLiuSir
Link: http://yoursite.com/2020/03/31/%E5%8F%8D%E5%B0%84/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶