Java代码在计算机上的三阶段
- 源代码阶段。源代码经过编译,生成class文件
- Class类对象阶段。成员变量被封装为Field对象,构造函数被封装为Constructor对象,成员方法被封装为Method对象
- Runtime运行时阶段
- 源代码阶段-->Class类对象阶段:ClassLoader将class加载进内存
反射好处:
- 可以在程序的运行过程中,操作这些对象
- 可以解耦,提高程序的可拓展性
获取Class对象的方式
- Class.ForName("全类名"):将字节码文件加载进内存,返回Class对象
- 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
- 类名.class:通过类名的属性class获取
- 对象.getClass():getClass()方法在Object类中定义着
- 注意:同一个字节码文件(*.class)在一次程序的运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个
Class对象功能
获取功能
- 获取成员变量们
- Field[] getFields():获取所有public修饰的成员变量
- Filed getField(String name)
- Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
- Field getDeclaredField(String name)
- 获取构造方法们
- Constructor<?>[] getConstructors()
- Constructor getConstructor(类<?>... parameterTypes)// 参数举例:(String.class, int.class)
- Constructor<?>[] getDeclaredConstructors()
- Constructor getDeclaredConstructor(类<?>... parameterTypes)
- 获取成员方法们
- Method[] getMethods()
- Method getMethod(String name, 类<?>... parameterTypes)
- Method[] getDeclaredMethods()
- Method getDeclaredMethod(String name, 类<?>... parameterTypes)
- 获取类名
Filed:成员变量
- 操作:
- 设置值
- void set(Object obj, Object value)
- 获取值
- 忽略访问权限修饰符的安全检查
Constructor:构造方法
- 创建对象
- T newInstance(Object... initargs)
- 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
Method:方法对象
- 执行方法:
- Object invoke(Object obj, Object... args)
- String getName():获取方法的名称
案例
- ReflectTest.java
package com.study;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectTest {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
// write your code here
/**
* 案例:写一个“框架”,在不改变类的任何代码的情况下,可以帮助我们创建任意类的对象,并且执行其中任意的方法
* 实现:1.配置文件:
* ClassName=com.study.refelct.Dog
* MethodName=sleep
* 2.反射
* 步骤:1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中
* 2.在程序中加载读取配置文件
* 3.使用反射技术来加载文件进内存
* 4.创建对象
* 5.执行方法
*/
Properties properties = new Properties();
ClassLoader classLoader = ReflectTest.class.getClassLoader();
properties.load(classLoader.getResourceAsStream("pro.properties"));
String className = properties.getProperty("ClassName");
String methodName = properties.getProperty("MethodName");
Class cls = Class.forName(className);
Object obj = cls.newInstance();
Method method = cls.getMethod(methodName);
method.invoke(obj);
}
}
- Dog.java
package com.study.refelct;
public class Dog {
public void sleep(){
System.out.println("dog sleep...");
}
}
- pro.properties
ClassName=com.study.refelct.Dog
MethodName=sleep