反射机制及应用
什么是反射
在程序运行状态中,对于任意一个类或对象,都能够获取到这个类的所有属性和方法(包括私有属性和方法),这种动态获取信息以及动态调用对象方法的功能就称为反射机制。简单来讲,通过反射,类对我们是完全透明的,想要获取任何东西都可以。
Class对象
我们创建的每一个类也都是对象,即类本身是java.lang.Class
类的实例对象。这个实例对象称之为类对象,也就是Class
对象。
Class
类的实例对象表示正在运行的Java
应用程序中的类和接口,也就是JVM
中的每一个实例,每一个类都有唯一的Class
对象Class
类没有公共的构造方法,Class
对象是在加载类时由Java
虚拟机自动构造的Class
对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法
获取Class对象的三种方式
- 可以在源代码阶段进行获取。
Class.forName(“全类名”)
。将字节码文件加载进内存,返回Class
对象,多用于配置文件,将类名定义的配置文件中。 - 在
Class
类对象阶段获取:类名.class
。此方式多用于参数的传递 - 在
Runtime
阶段获取:new 类名().getClass()
。该方法是定义在Object
类中的(所有类均继承自Object
)方法,因此所有的类都会继承该方法。多用于对象获取字节码的方式。
获取Class对象案例
public class GetClass {
@Test
public void classForName() throws ClassNotFoundException {
// 方式一 Class.forName("全类名")
final Class<?> clazz1 = Class.forName("cn.wujiwen.basic.reflect.ExampleClass");
System.out.println("class1:" + clazz1);
}
@Test
public void nameClass(){
// 方式二 类名.class
final Class<ExampleClass> clazz2 = ExampleClass.class;
System.out.println("class2:" + clazz2);
}
@Test
public void ObjectGetClass(){
// 方式三 实例对象.getClass()
ExampleClass exampleClass = new ExampleClass();
Class<?> clazz3 = exampleClass.getClass();
System.out.println("class3:" + clazz3);
}
// 同一个节码文件(*.class)在一次程序运行过程中,只会被加载一次,无论通过哪一种方式获取的Class对象都是同一个。
@Test
public void all() throws ClassNotFoundException {
Assertions.assertSame(Class.forName("cn.wujiwen.basic.reflect.ExampleClass") , ExampleClass.class);
}
}
Class对象的功能
这里将简单记录三种常用的功能,更多方法可完整阅读class
源码
1、获取成员变量
//获取所有public修饰的成员变量
Field[] getFields()
//获取指定名称的public修饰的成员变量
Field getField(String name)
//获取所有的成员变量,不考虑修饰符
Field[] getDeclaredFields()
//获取指定的成员变量,不考虑修饰符
Field getDeclaredField(String name)
2、获取构造方法
//获取所有public修饰的构造函数
Constructor<?>[] getConstructors()
//获取指定的public修饰的构造函数
Constructor<T> getConstructor(类<?>... parameterTypes)
//获取所有的构造函数,不考虑修饰符
Constructor<?>[] getDeclaredConstructors()
//获取指定的构造函数,不考虑修饰符
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) //获取指定的构造函数,不考虑修饰符
3、获取成员方法
//获取所有public修饰的成员方法
Method[] getMethods()
//获取指定名称的public修饰的成员方法
Method getMethod(String name, 类<?>... parameterTypes)
//获取所有的成员方法,不考虑修饰符
Method[] getDeclaredMethods()
//获取指定名称的成员方法,不考虑修饰符
Method getDeclaredMethod(String name, 类<?>... parameterTypes)
下面我们一个一个类测试一下,先准备以上功能方法所需要用到的类、属性信息
public class ExampleClass {
// public修饰的属性
public String publicField;
// private 修饰的属性
private String privateField;
// 默认
String defaultField;
// protected 修饰的户型
protected String protectedField;
// protected 无参数构造,与public无参数构造冲突,会发生覆盖操作
protected ExampleClass(){
}
// public 一个参数的构造函数
public ExampleClass(String privateField){
this.privateField = privateField;
}
public void publicMethod(){
}
private void privateMethod()