反射是什么?
首先得知道,java对象在被编译成后是class文件,运行时在内存中是以Class对象呈现。Object对象提供了获取Class对象的方法,obj.getClass(),通过这个方法就可以获取到目标对象的Class对象。而我们通过Class对象可以得到目标对象的所有属性以及方法的过程称之为反射。换成官方一点的术语就是:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
怎么用?
先看看最简单的用法吧
Class.forName("");
该方法入参是一个类名,一定是全类名。
可以看到,通过全类名可以获取该类的Class对象,然后通过类构造器的newInstance()方法实例化一个对象。
newInstance()
通过该方法获取一个对象。
从上诉源码中发现它返回的是一个泛型,而且在jdk9的时候被标记成一个过期方法,推荐新的方法使用类构造器的newInstance()方法
getConstructor()
从名字上不难发现,这是获取目标类的构造器的。
上图可以看到该方法的入参是一个不定长参数,作用就是为了过去不同的构造器。而构造器中拥有一个newInstance()方法,就是上诉所提到的替代Class对象的newInstance()方法
Field对象
getFields()获取获取类和接口的所有可访问的字段,也就是public修饰的字段。
上图分别为当前类page,和超类Test,通过输出可以看到,有且只能输出超类的username,因为只有该字段是public的,看下图:
getDeclaredFields()返回的是当前类的所有字段数组,即包括除了public以外的三种修饰符修饰的属性
当然无论getDeclaredFields()还是getFields()对于他们都是获取一个数组,那么怎么获取一个指定的字段呢?
由上图可以看到可以根据getDeclaredField()方法传入一个属性名就可以获取到相对应的属性对象了,那么getField()同理
从上诉的例子不难发现,获取的属性都是一个Field对象,先看这个类
可以看到Field对象的成员我们常用的有type(类型),name(名字),modifiers(修饰),annotations(注解),等
可以发现getModifiers返回的是一个int,怎么判断呢?我们可以看看Modifier类,
该类提供了可用的方法,这里就不作演示了。
那么获取值的方法说了,如果反射只能获取值那就很鸡肋了,当然他自然是可以设置值的。获取是通过get方法,既然这样猜也能猜出来设置一定是set了,不过set需要两个入参,第一个是目标对象,第二个是值
Method
不难发现这个对象指的是方法
getMethods()获取当前类以及超类所有的公共方法,也就是public修饰的方法
为此我再超类添加了受保护的方法test,page类添加demo
自行输出,这里就不截图了太长了。可以发现无论是超类的受保护的方法还是当前类的私有方法都是获取不到的。
怎么获取一个的所有方法呢?照猫画虎,既然属性是getDeclaredField,那么方法是不是getDeclaredMethod?
通过输出可以看到,私有方法也是可以获取到的。
来看看Method类吧
我用红色框起来的是常用的属性简单验证几个
这里通过getDeclaredMethod()方法获取指定的Method类,他有两个入参,第一个是方法名,第二个是形参类型。第二个入参是一个不定长参数(这个不用解释吧,昨天竟然有人问我这个...)。
同样的既然能获取到这个方法的所有属性了,那么怎么执行呢?
通过反射执行一个方法离不开invoke(),这个方法是可以执行一个方法。
可以看到invoke()方法有两个入参,第一个是对象,就是要执行该方法的对象。第二个还是一个不定长参数,显而易见就是这个方法的入参了。返回是一个object。
一下是执行结果
其中 a=3 是demo方法内执行的输出,下边的输出是拿到返回值输出的该方法的返回值。
Annotation
再来看看注释,无论是Class对象还是Filed,又或者Method,他们都是有一个获取注释的方法。(就是注解)
不知道你们有没有发现Class,Method,Filed都是final修饰的类,就是说不能继承。那么Annotation是一个接口。。。当然了解这个的话你应该知道Annotation是所有注解的父类。也可以说是超类吧
这个不是重点,重点是怎么用!
isAnnotationPresent():判断是否使用某注解修饰。入参是注解Class对象,返回是boolean
getAnnotation():获取注解对象
只要获取了注解对象那么这个注解的所有属性就都可以获取了。
写的不好,欢迎大佬来吐槽。