反射机制:是在运行状态下,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意属性和方法;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
它的工作原理是这样的:当一个字节码文件加载到内存的时候,JVM会对该字节码进行解刨,然后创建一个对象的Class对象,JVM把字节码的信息全部都存储的到该Class对象中,我们只要获取到Class对象,就可以使用该对象设置对象的属性或者调用对象的方法等操作。
反射可以动态获取类的信息,进一步实现需要的功能。
例如:Spring框架通过XML文件描述类的基本信息,使用反射机制动态装配对象。
为什么需要反射?
Java程序中的对象在运行时可以表现为两种类型,即编译时类型和运行时类型。例如:Person p = new Student();这行代码将会生成一个p变量,该变量的编译时类型未Person,运行时类型为Student。
有时,程序在运行时接收到外部传入的一个对象,该对象的编译类型是Object,但程序又需要调用该对象的运行时类型的方法。这就要求程序需要在运行时发现对象和类的真实信息,而解决这个问题有以下两种做法:
1.第一种做法是假设在编译时和运行时都完全知道类型的基本信息,在这种情况下,可以先使用instanceof运算符进行判断,再利用强制类型转换将其转换成其运行时类型的变量即可。
2.第二种做法是编译时根本无法预知该对象和类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息,这就必须使用反射。
具体来说,通过反射机制,可以实现如下的操作:
程序运行时,可以通过反射获得任意一个类的Class对象,并通过这个对象查看这个类的信息。
程序运行时,可以通过反射创建任意一个类的实例,并访问该实例的成员。
程序运行时,可以通过反射机制生成一个类的动态代理类或者动态代理对象。
获取Class类对象的三种方式
1.类名.class属性
2.对象名.getClass()方法
3.Class.forName(全类名)方法
反射获取构造方法并应用
1.Class类获取构造方法对象和方法
Constructor<?>[] getConstructors() 返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors() 返回所有构造方法对象的数组
Constructor getConstructor(Class<?>… parameterTypes) 返回单个公共构造方法对象
Constructor getDeclaredConstructor(Class<?>… parameterTypes) 返回单个构造方法对象
2.Constructor类用于创建对象的方法
T newInstance(Object…initargs) 根据指定的构造方法创建对象
setAccessible(boolean flag) 设置为true,表示取消访问检查
3.Class类获取成员变量对象的方法
Field[] getFields() 返回所有公共成员变量对象的数组
Field[] getDeclaredFields() 返回所有成员变量对象的数组
Field getField(String name) 返回单个公共成员变量对象
Field getDeclaredField(String name) 返回单个成员变量对象
4.Field类用于给成员变量赋值的方法
void set(Object obj, Object value) 赋值
Object get(Object obj) 获取值
5.Class类获取成员方法对象的方法
Method[] getMethods() 返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods() 返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>… parameterTypes) 返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>… parameterTypes) 返回单个成员方法对象
6.Method类用于执行方法的方法
Object invoke(Object obj, Object… args) 运行方法
参数说明:
- 参数一: 用obj对象调用该方法
- 参数二: 调用方法的传递的参数(如果没有就不写)
反射的应用
Java的反射机制在实际项目中应用广泛,常见的应用场景有:
使用JDBC时,如果要创建数据库的连接,则需要先通过反射机制加载数据库的驱动程序;
多数框架都支持注解/XML配置,从配置中解析出来的类是字符串,需要利用反射机制实例化;
面向切面编程(AOP)的实现方案,是在程序运行时创建目标对象的代理类,这必须由反射机制来实现。