反射技术快速上手 什么是 Java 反射Java 反射Reflection是程序运行时动态获取类信息、构造对象、调用属性 / 方法的机制核心是操作编译后的Class对象.class字节码文件的内存表示。核心能力构造任意类的对象获取对象所属类的完整信息访问 / 修改类的成员变量包括私有调用类的任意方法包括私有反射核心组件组件含义Class类的字节码对象反射的源头Constructor类的构造器Field类的成员变量Method类的方法 获取 Class 对象的 2 种方式类名.class编译期确定ClassUser userClass User.class;对象.getClass ()运行期从对象获取User user new User(); Class? extends User userClass user.getClass();常用 Class API方法名作用getName()获取 包名 类名getSimpleName()获取 类名getDeclaredConstructor(Class?... params)根据参数类型获取构造器无视修饰符getDeclaredConstructors()获取所有声明的构造器 反射 API 分类getvsgetDeclared1.getXxx()获取公有成员只能获取public修饰的成员getMethod()会递归查找本类 父类的公有方法2.getDeclaredXxx()获取本类所有成员可以获取private/protected/public修饰的成员getDeclaredMethod()只查找本类的方法不查父类API 形式访问范围父类可见性getField()仅公有可见本类 父类getDeclaredField()本类所有不可见仅本类getMethod()仅公有可见本类 父类getDeclaredMethod()本类所有不可见仅本类 为什么要学反射是 Java 高级技术、框架底层的标配Spring、MyBatis 等都依赖反射实现依赖注入、ORM 映射阅读源码、编写中间件时必须掌握实现动态代理、泛型数组创建等高级功能 示例获取构造器// 1. 获取 Class 对象 ClassUser userClass User.class; // 2. 获取指定参数的构造器 ConstructorUser constructor userClass.getDeclaredConstructor(int.class, String.class); System.out.println(constructor.getName() 参数个数 constructor.getParameterCount()); // 3. 获取所有构造器 Constructor?[] constructors userClass.getDeclaredConstructors(); for (Constructor? c : constructors) { System.out.println(c.getName() 参数个数 c.getParameterCount()); }反射技术实战之对象创建 Constructor 核心作用Constructor类是反射中用于创建对象的核心 API最终目的是实例化类对象。 常用newInstance方法方法签名说明要求T newInstance()调用无参构造器创建对象类必须提供 public 权限的无参构造器T newInstance(Object... initargs)调用指定参数构造器创建对象需先获取对应参数列表的 Constructor✅ JDK 9 后推荐使用Constructor.newInstance()替代旧的Class.newInstance()。 反射创建对象的标准步骤获取 Class 对象通过类名.class或全类名加载获取构造器调用getDeclaredConstructor(...)或getConstructor(...)创建对象调用constructor.newInstance(...)并传入初始化参数 代码示例无参构造器创建对象public static void test2() throws Exception { // 1. 获取 Class 对象 ClassUser clazz User.class; // 2. 获取无参构造器并创建对象 User user clazz.getDeclaredConstructor().newInstance(); // 3. 初始化属性 user.setAge(11); user.setName(老王); System.out.println(user); }有参构造器创建对象public static void test3() throws Exception { // 1. 获取 Class 对象 ClassUser clazz User.class; // 2. 获取指定参数的构造器int, String ConstructorUser constructor clazz.getConstructor(int.class, String.class); // 3. 传入参数创建对象 User user constructor.newInstance(21, 冰冰); System.out.println(user); } 为什么 POJO 必须显式写空构造器反射创建对象框架如 Spring通过反射调用无参构造器实例化 Bean子类继承子类默认调用super()父类必须提供无参构造器否则编译报错 关键注意点getConstructor(...)只能获取public构造器getDeclaredConstructor(...)可获取所有权限构造器包括private需配合setAccessible(true)绕过权限检查无参构造器必须是public或通过setAccessible(true)打开权限才能被newInstance()调用反射技术实战之方法和属性实战 反射获取方法与属性核心知识点一、获取类的方法Method方法名作用范围权限要求getMethods()当前类 父类仅 public 方法getDeclaredMethods()仅当前类所有权限private/protected/publicMethod 常用 APIgetReturnType()获取方法返回值类型getParameterTypes()获取方法参数类型数组getModifiers()获取方法修饰符整数对应Modifier类常量getExceptionTypes()获取方法声明抛出的异常类型代码示例public static void test2() throws Exception { // 1. 获取 Class 对象 ClassUser clazz User.class; // 2. 获取无参构造器并创建对象 User user clazz.getDeclaredConstructor().newInstance(); // 3. 初始化属性 user.setAge(11); user.setName(老王); System.out.println(user); }二、获取类的属性Field表格方法名作用范围权限要求getFields()当前类 父类仅 public 属性getDeclaredFields()仅当前类所有权限private/protected/publicField 常用 APIgetType()获取属性类型getName()获取属性名getModifiers()获取属性修饰符整数对应Modifier类常量代码示例public static void test3() throws Exception { // 1. 获取 Class 对象 ClassUser clazz User.class; // 2. 获取指定参数的构造器int, String ConstructorUser constructor clazz.getConstructor(int.class, String.class); // 3. 传入参数创建对象 User user constructor.newInstance(21, 冰冰); System.out.println(user); }三、关键区别总结API 类型getXxx()getDeclaredXxx()范围本类 父类仅本类权限仅 public所有权限适用方法 / 属性 / 构造器方法 / 属性 / 构造器 补充说明getModifiers()返回的整数可通过Modifier.toString(int mod)转换为可读字符串如public static final。若要访问 / 修改私有属性或调用私有方法需先调用field.setAccessible(true)或method.setAccessible(true)绕过权限检查。【重点】保留反射技术实践之属性值操作 反射暴力破解权限setAccessible(true)当构造器、方法、属性是private等受限权限时Java 会阻止直接访问此时可以通过setAccessible(true)暴力破解权限Constructor/Method/Field都支持此方法。 核心 API 说明方法作用setAccessible(true)临时关闭 Java 访问权限检查允许访问私有成员Field.get(Object obj)获取 obj 对象上该 Field 的属性值Field.set(Object obj, Object value)给 obj 对象上该 Field 设置属性值✅ 案例 1调用私有构造器创建对象public static void test4() throws Exception { // 1. 获取 Class 对象 ClassUser clazz User.class; // 2. 获取私有构造器无参 ConstructorUser constructor clazz.getDeclaredConstructor(); // 3. 暴力破解权限 constructor.setAccessible(true); // 4. 创建对象 User user constructor.newInstance(); user.setAge(11); user.setName(老王); System.out.println(user); }✅ 案例 2操作私有属性读写public static void main(String[] args) throws Exception { // 1. 获取 Class 对象 ClassProduct clazz Product.class; // 2. 获取私有构造器并创建对象 ConstructorProduct constructor clazz.getDeclaredConstructor(); constructor.setAccessible(true); Product product constructor.newInstance(); System.out.println(product); // 初始值Product(price0, titlenull) // 3. 获取私有属性 title Field titleField clazz.getDeclaredField(title); // 4. 破解权限 titleField.setAccessible(true); // 5. 设置属性值 titleField.set(product, 小滴云架构大课); // 6. 读取属性值 System.out.println(titleField.get(product)); // 输出小滴云架构大课 System.out.println(product); // 最终Product(price0, title小滴云架构大课) }⚠️ 关键注意事项setAccessible(true)是临时生效仅对当前Constructor/Method/Field对象有效不会修改类的原始权限。安全风险破坏封装性可能导致代码不稳定框架底层常用业务代码需谨慎。适用范围所有反射成员构造器、方法、属性都支持此 API。 总结权限受限→ 调用getDeclaredXxx()获取本类私有成员。破解权限→ 调用setAccessible(true)关闭访问检查。执行操作→ 调用newInstance()/invoke()/get()/set()完成业务逻辑。【重点】反射技术之invoke运行类的指定方法 反射运行指定方法Method.invoke()反射的最终目的是动态调用类的方法包括私有方法、静态方法核心 API 是Method.invoke(Object obj, Object... args)。invoke方法核心说明签名public Object invoke(Object obj, Object... args)参数说明obj调用方法的实例对象若为静态方法传 nullargs方法的入参可变长度无参则传 null 或省略返回值方法的返回值若无返回值返回 null私有方法调用前提调用前必须执行method.setAccessible(true)破解权限。✅ 实战代码示例调用普通成员方法含私有public static void test7() throws Exception { // 1. 获取 Class 对象 ClassUser clazz User.class; // 2. 创建对象若调用非静态方法 ConstructorUser declaredConstructor clazz.getDeclaredConstructor(); declaredConstructor.setAccessible(true); // 破解私有构造器 User user declaredConstructor.newInstance(); user.setName(老王); // 3. 获取指定方法名称参数类型 Method sayMethod clazz.getDeclaredMethod(say, String.class); // 4. 破解权限如果是私有方法 sayMethod.setAccessible(true); // 5. 调用方法 // 参数1调用者对象 // 参数2方法实参 Object returnValue sayMethod.invoke(user, 大钊老师); // 6. 处理返回值 System.out.println(方法返回值: returnValue); }调用静态方法// 获取静态方法 Method sleepMethod clazz.getDeclaredMethod(sleep, String.class); sleepMethod.setAccessible(true); // 调用静态方法第一个参数传 null Object result sleepMethod.invoke(null, 冰冰); System.out.println(静态方法返回值: result); 完整代码模板// 1. 获取类对象 Class? clazz User.class; // 2. 获取方法对象 Method method clazz.getDeclaredMethod(方法名, 参数类型.class); // 3. 暴力破解如果是私有方法 method.setAccessible(true); // 4. 执行方法 // 非静态方法invoke(对象, 参数) // 静态方法invoke(null, 参数) Object result method.invoke(实例对象, 实参);⚠️ 常见异常与注意事项NoSuchMethodException方法名或参数类型不匹配需仔细核对getDeclaredMethod(name, params)。IllegalAccessException未调用setAccessible(true)访问私有方法。IllegalArgumentException传入的对象类型与方法所属类不匹配或参数类型错误。InvocationTargetException方法内部执行抛出异常反射会包装此异常需通过e.getTargetException()获取真实异常。 核心流程总结获取 Class→ClassUser clazz User.class;获取 Method→clazz.getDeclaredMethod(say, String.class);破解权限→method.setAccessible(true);调用 Method→method.invoke(user, 参数);