反射:框架设计的灵魂
框架:半成品的软件。可以在框架的基础上进行软件开发,简化编码
反射:将类的各个组成部分封装为其他对象,这就是反射机制
好处:
①可以在程序运行过程中,操作这些对象。
②可以解耦,提高程序的可扩展性。
反射的操作
- 获取class对象的方式:
Class.forName(”全类名“):将字节码文件加载到内存,返回class对象(多用于配置文件,将类名定义在配置文件中。读取文件,加载类)
类名.class:通过类名的属性class获取(多用于参数的传递)
对象.getClass():getClass()方法在Object类中定义的(多用于对象的获取字节码的方式)
- 使用class对象的功能
- 获取功能:
①获取成员变量们:
方法 |
说明 |
getFields() |
获取所有public修饰的成员变量 |
getField(String name) |
获取指定名称的public修饰的成员变量 |
getDeclaredFields() |
获取所有成员变量,不考虑修饰符 |
getDeclaredField(String name) |
获取指定的成员变量 |
忽略访问权限修饰符的安全检查暴力反射
成员变量.setAccessible(true)
②获取构造方法们:
方法 |
说明 |
getConstructors() |
获得所有public修饰的构造方法 |
getConstructor(类<?>...parameterTypes) |
根据参数返回public修饰的指定的构造方法 |
getDeclaredConstructors() |
|
getDeclaredConstructor(类<?>...parameterTypes) |
|
忽略访问权限修饰符的安全检查暴力反射
构造方法对象.setAccessible(true)
③获取成员方法们:
方法 |
说明 |
getMethods() |
获得public修饰的成员方法 |
getMethod(String name,类<?>...parameterTypes) |
|
getDeclaredMethods() |
获得所有的成员方法 |
getDeclaredMethod(String name,类<?>...parameterTypes) |
|
忽略访问权限修饰符的安全检查暴力反射
成员方法.setAccessible(true)
④获取类名
⑤获取注解
方法 |
说明 |
getAnnotation(注解名.class) |
获得该类的注解对象 |
⑥判断有无注解
方法 |
说明 |
(class,method,field).isAnnotationPersent() |
判断当前类,方法,变量是否有注解 |
- 对成员变量对象的操作
方法 |
说明 |
get(Object o) |
获得成员变量的值 |
set(Object,value) |
设置成员变量的值 |
- 对构造方法对象的操作
方法 |
说明 |
newInstance(Object...initargs) |
创建对象 |
- 对注解对象的操作
方法 |
说明 |
注解对象.注解属性(抽象方法)名 |
获得属性值 |
案例
写一个框架,可以帮我们创建任意类的对象,并且执行其中任意的方法
- 实现
①配置文件
②反射
- 步骤
①将需要创建的对象的全类名和需要执行的方法定义到配置文件中
②在程序中加载读取配置文件(properties.load())
③使用反射技术来加载类文件进内存
④创建对象
⑤执行方法
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {
// 1. 加载配置文件
//1.1创建properties对象
Properties properties = new Properties();
//1.2加载配置文件,转化为一个Map
//1.2.1获取class目录下的配置文件
ClassLoader classLoader = test.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
properties.load(resourceAsStream);
// 2.获取配置文件中定义的数据
String className = properties.getProperty("className");
// 3.加载该类到内存
Class<?> aClass = Class.forName(className);
// 4.创建对象
Constructor<?> constructor = aClass.getConstructor();
Object o = constructor.newInstance();
// 5.创建方法对象
String method1 = properties.getProperty("methodName");
Method method = aClass.getMethod(method1);
Object str = method.invoke(o);
System.out.println(str);
}
}
网友评论