反射
java类拥有三个阶段。
第一个阶段时源代码阶段,此时java类存在于.java
后缀的文本文件中。
第二阶段时字节码阶段,此时java类存在于.class
的字节码文件中。
第三个阶段是运行时阶段,任何类在被jvm读取的同时都会自动创建一个java.lang.Class
对象,该对象没有公开的构造方法,是由jvm自动创建的。
通过java.lang.Class
对象就可以访问到jvm中对象类的信息。
获取Class对象
有三种方法可以获取Class对象。
一种当类未被加载进内存时,通过Class.forName
方法,提供完整的类路径(包含包名)。该方法将返回一个Class对象
二种是当类已被加载,直接使用类名.class
属性,只能够直接获取到类对应的Class对象
三种是当类已经被加载,并且创建了类实例对象,直接使用对象.getClass
方法,就能够从对象实例获取对应的Class对象。
使用Class对象
为了获取类的Class对象,实际也就是通过它获取他其中的成员变量,成员函数,注解以及创建类的实例。
获取成员变量,函数以及注解等,直接使用getField
/ getFields
/ getDeclaredField
/ getDeclaredFields
/ getAnnotation
/ getAnnotations
/ getConstructor
/ getConstructors
/ getMethod
getMethods
/ getDeclareMethod
/ getDeclareMethods
等等
Class类对象的实例方法有很多就不一一列举了,但是他们的大概规律是,对于复数形式的是获取数组,单数形式的是获取对应的对象。同时对于获取的对象也就是java.lang.reflect
包下的反射类对象,如Method
Field
Annotation
。
对于带有Declared
的和不带Declared
的方法名的区别是,前者能够获取到任何访问权限的成员,而后者只能够访问当公开的成员。
同时即使获取了私有的成员也不能够直接使用,直接使用java将会抛出异常。需要对成员设置setAccessible(true)
来限制忽略警告。
Method / Constructor 类的使用
两者的使用很简单,在该类对象以后,直接调用invoke
/ newInstance
方法来执行/创建对象。或者可以获取其上的注解,返回值类型,参数个数等等其他信息。
Field / Annotation 的使用
获取了Field / Annotation对象以后也就是需要获取对应的信息。
对于Field对象,使用get方法获取指定对象上该字段的值,如果是静态字段需要提供类,而对于实例成员就需要提供实例对象了。或者可以获取其上的Annotation等等。
Annotation对象一般是作为需要获取注释的时候作为参数提供。