概念:将类的各个部分封装成其他对象,这就是反射机制
获取Class对象的方式:
- Class.forName("全类名"):将字节码文件加载到内存,返回class对象。多用于配置文件,在配置文件中定义类名,通过读取配置文件来加载类
- 类名.class:通过类名的属性class获取。多用于参数的传递
- 对象.getClass():Object类中的getClass方法。
结论:这三种方式获取的对象是相同的,这说明同一个字节码文件(*.class)在一次程序运行的过程中只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
Class对象功能:
获取成员变量们:getFields() / getField(String name) //只能获取public修饰的
getDeclaredFields() / getDeclaredField(String name) //获取public、protected、private修饰的
获取构造方法们:getConstructors() / getConstructor(类<?>...parameterTypes)
getDeclaredConstructors() / getDeclaredConstructor(类<?>...parameterTypes)
获取成员方法们:getMethods() / getMethod(String name,类<?>...parameterTypes)
getDeclaredMethods() / getDeclaredMethod(String name,类<?>...parameterTypes)
获取类名:getName()
一、Field:成员变量
- 设置值 set(Object,Object)
- 获取值 get(Object)
- 忽略访问修饰符的安全检查 setAccessible(true)
使用非public修饰的属性、方法时会提示非法访问异常的错误(illegalAccessException),需要忽略访问修饰符的安全检查:
setAccessible(true) 这种方法也称为暴力反射。
二、Constructor:构造方法
- 创建对象 newInstance(Object....intiargs)
三、Method:方法对象
- 执行方法:Object invoke(Object,Object....args)
- 获取方法名称:String getName
例:personClass.getConstructor(String.class,int.class);
personClass.getMethod(name:"eat")
personClass.getMethod("eat",String.class)
案例
实现:
1.配置文件
2.反射
步骤:
1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中
2.在程序中加载读取配置文件
3.使用反射来加载类文件进内存
4.创建对象
5.执行方法
/**
* 不改变该类任何代码,可以创建任意类的对象,可以执行任意方法
*/
public class ReflectTest {
public static void main(String[] args) throws Exception {
// 加载配置文件
Properties pro = new Properties();// 创建properties对象
ClassLoader classloader = ReflectTest.class.getClassLoader();// 获得当前类的类加载器
InputStream is = classloader.getResourceAsStream("pro.properties");// 获取class目录下的配置文件
pro.load(is);
// 获取配置文件中定义的数据
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
// 加载该类进内存
Class<?> cls = Class.forName(className);
// 创建对象
Object obj = cls.getConstructor().newInstance();
// 获取方法对象
Method method = cls.getMethod(methodName);
// 执行方法
method.invoke(obj);
}
}
className=practice.Person
methodName=eat
public class Person {
public void eat() {
System.out.println("eat food");
}
}