反射
约 1639 字大约 5 分钟
2026-04-04
反射
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
加载
就是指将class文件读入内存,并为之创建一个Class对象。
任何类被使用时系统都会建立一个Class对象。
连接
验证是否有正确的内部结构,并和其他类协调一致
准备负责为类的静态成员分配内存,并设置默认初始化值
解析将类的二进制数据中的符号引用替换为直接引用
初始化
- 创建类的实例
- 类的静态变量,或者为静态变量赋值
- 类的静态方法
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类
类加载器
Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
System ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
创建反射对象
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的
(1)通过Object类中的getObject()方法,对象.getClass();
Student s1 = new Student();
Class<? extends Student> s1Class = s1.getClass();
(2)通过 类名.class 获取到字节码文件对象。任意数据类型都具备一个class静态属性
Class<Student> studentClass = Student.class;
(3)通过Class类中的方法。将类名作为字符串传递给Class类中的静态方法forName(),Class.forName(全限定类名)
Class<?> stuReflectClass = Class.forName("com.pojo.Student");获取构造方法
返回一个构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取public修饰, 指定参数类型所对应的构造方法
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取指定参数类型所对应的构造方法(包含私有的)
返回多个构造方法
public Constructor<?>[] getConstructors() 获取所有的public 修饰的构造方法
public Constructor<?>[] getDeclaredConstructors() 获取所有的构造方法(包含私有的)
public T newInstance(Object... initargs) 通过构造方法类Constructor中的方法,创建对象
暴力访问, 通过setAccessible(boolean flag)方法
// 获取所有public构造方法
Constructor<?>[] publicCons = stuReflectClass.getConstructors();
// 获取有参构造方法
Constructor<?> con = stuReflectClass.getConstructor(String.class, String.class, String.class, String.class, String.class, String.class);
// 创建新的实例,使用public构造器
Object o = con.newInstance("admin", "123", "男", "本科", "玩游戏");
Student stu1 = (Student) o;
// 获取所有的构造方法,包括private
Constructor<?>[] declaredCons = stuReflectClass.getDeclaredConstructors();
// 获取私有构成方法
Constructor<?> declaredCon = stuReflectClass.getDeclaredConstructor(String.class);
// 取消java语法访问检查
declaredCon.setAccessible(true);
// 创建新的实例,使用私有构造器
Object root = declaredCon.newInstance("root");
Student stu2 = (Student) root;获取成员变量
返回一个成员变量
public Field getField(String name) 获取指定的 public修饰的变量
public Field getDeclaredField(String name) 获取指定的任意变量
返回多个成员变量
public Field[] getFields() 获取所有public 修饰的变量
public Field[] getDeclaredFields() 获取所有的 变量 (包含私有)
通过方法,给指定对象的指定成员变量赋值或者获取值
public void set(Object obj, Object value) 在指定对象obj中,将此 Field 对象表示的成员变量设置为指定的新值
public Object get(Object obj) 返回指定对象obj中,此 Field 对象表示的成员变量的值
Student s1 = new Student();
// 获取所有s1Class字段
Field[] fields = s1Class.getFields();
// 获取所有字段account,不包括private
Field account = studentClass.getField("account");
account.setAccessible(true);
account.set(s1, "root");
Object user = account.get(s1);
// 获取所有s1Class字段,包括私有字段
Field[] fields = s1Class.getDeclaredFields();
// 获取所有字段account,不包括private
Field account = studentClass.getDeclaredField("account");
account.setAccessible(true);
account.set(s1, "root"); //account为获取的字段反射对象,s1为创建的Student对象
Object user = *account.get(s1)**;//account为获取的字段反射对象,s1为创建的Student对象获取成员方法
返回获取一个方法:
public Method getMethod(String name, Class<?>... parameterTypes) 获取public 修饰的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 获取任意的方法,包含私有的
参数1: name 要查找的方法名称; 参数2: parameterTypes 该方法的参数类型
返回获取多个方法:
public Method[] getMethods() 获取本类与父类中所有public 修饰的方法
public Method[] getDeclaredMethods() 获取本类中所有的方法(包含私有的)调用指定方法
public Object invoke(Object obj, Object... args)
执行指定对象obj中,当前Method对象所代表的方法,方法要传入的参数通过args指定。
public static void main(String[] args) throws Exception {
// 获取反射对象
Class<?> stuClass = Class.forName("com.pojo.Student");
// 获取反射对象对应的私有构造方法
Constructor<?> declaredConstructor = stuClass.getDeclaredConstructor(String.class);
// 取消java语言访问检查
declaredConstructor.setAccessible(true);
// 创建新的实例
Object root = declaredConstructor.newInstance("root");
// 获取反射对象对应的punlic成员方法
Method method = stuClass.getMethod("method", null);
// 执行方法
method.invoke(root, null);
// 获取反射对象对应的private成员方法
Method method1 = stuClass.getDeclaredMethod("method", String.class);
// 取消java语言访问检查
method1.setAccessible(true);
// 执行方法
System.out.println(method1.invoke(root, "sss"));
}通过获取使用指定注解的属性并通过get方法获取值
if (result == null) {
return;
}
Class<? extends BiweeklyQualitysisReportCommonResult> resultClass = result.getClass();
Map<Field, Class<? extends BiweeklyQualitysisReportCommonResult>> fieldAndClassMap = new HashMap<>();
Map<String,Object> fieldAndObjMap = new HashMap<>();
while (resultClass != null) {
Field[] declaredFields = resultClass.getDeclaredFields();
if (declaredFields != null && declaredFields.length > 0) {
for (Field field : declaredFields) {
fieldAndClassMap.put(field, resultClass);
}
}
resultClass = (Class<? extends BiweeklyQualitysisReportCommonResult>) resultClass.getSuperclass();
}
for (Map.Entry<Field, Class<? extends BiweeklyQualitysisReportCommonResult>> entry : fieldAndClassMap.entrySet()) {
Field field = entry.getKey();
Class<? extends BiweeklyQualitysisReportCommonResult> clazz = entry.getValue();
if (field.isAnnotationPresent(FtlMapperAnnotation.class)) {
FtlMapperAnnotation ftlMapperAnnotation = field.getAnnotation(FtlMapperAnnotation.class);
String mapperName = ftlMapperAnnotation.mapperName();
try {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(mapperName, clazz);
Method method = propertyDescriptor.getReadMethod();
Object object = method.invoke(result);
fieldAndObjMap.put(mapperName, object);
} catch (IntrospectionException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
if (fieldAndObjMap != null && fieldAndObjMap.size() > 0) {
for (Map.Entry<String, Object> entry : fieldAndObjMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value == null) {
continue;
}
if (value instanceof String) {
wordDataMap.addKeyForObj(key, String.valueOf(value));
} else if (value instanceof List) {
wordDataMap.addKeyForArray(key, (List<Object>) value);
} else {
throw new InnerSystemException("only allow String or Collection Type!");
}
}
}贡献者
更新日志
2026/4/5 03:39
查看所有更新日志
fb8bc-更新为vuepress于