简单记录一下Java中反射相关的知识点,记录于此,方便自己查阅和学习。
正文
什么是反射
反射(Reflection)是指程序在运行时,能够动态获取类的结构信息并操作对象的能力。
换句话说:
反射原理
JVM在类加载阶段生成Class对象(Class对象保存了类的完整结构信息)
反射通过native方法 + 方法表访问这些信息
invoke()内部会做:
权限检查
方法查找
参数装箱拆箱
最终调用目标方法
为什么需要反射
反射主要解决的是:
运行时动态加载类
解耦调用者和具体实现
支持框架级别的通用能力
典型场景:
IDE、热部署、插件机制
Spring IOC(根据类名创建 Bean)
MyBatis(Mapper 接口 → SQL 执行)
Jackson / Fastjson(对象 ↔ JSON)
反射能干什么
反射可以或类的信息:构造方法、属性、方法以及私有成员。
| 能力 | 说明 |
|---|---|
| 获取类信息 | 类名、修饰符、父类、接口 |
| 获取构造方法 | 创建对象 |
| 获取属性 | 读取 / 修改字段 |
| 获取方法 | 调用方法 |
| 操作私有成员 | 突破访问控制 |
示例
获取Class对象的三种方式
// 1. 类名.class Class<?> c1 = User.class; // 2. 对象.getClass() User user = new User(); Class<?> c2 = user.getClass(); // 3. Class.forName() Class<?> c3 = Class.forName("com.example.User");
创建对象
Class<?> clazz = Class.forName("com.example.User"); Object obj = clazz.getDeclaredConstructor().newInstance();
调用方法
Method method = clazz.getMethod("setName", String.class); method.invoke(obj, "Tom");
操作属性(包括 private)
Field field = clazz.getDeclaredField("name"); field.setAccessible(true); // 突破 private field.set(obj, "Jerry");
获取构造器
Constructor<?> constructor = clazz.getConstructor(String.class, int.class); Object obj = constructor.newInstance("Tom", 18);
优缺点
优点
提高 灵活性 & 扩展性
降低 硬编码
支撑 框架和组件解耦
缺点
性能较差
破坏封装(可访问 private)
代码可读性差
编译期无法发现错误
问答
反射创建对象为什么不用 new?
编译期不确定类名,需要运行时动态加载。
反射调用方法慢在哪?
权限检查
参数包装
native调用
JIT优化受限
反射能调用 private 方法,为什么还能用?
通过setAccessible(true)跳过访问控制,但破坏了封装设计
getMethod和 getDeclaredMethod区别
方法 范围 getMethod 只能获取public getDeclaredMethod 本类声明的所有方法(含 private)
小结
反射是Java在运行时动态获取类信息和操作对象的一种机制
通过反射可以在运行时获取类的构造方法、属性和方法,并可以调用私有成员
反射的核心是Class类及其相关的Constructor、Field、Method。
反射广泛应用于 Spring、MyBatis 等框架中,用来实现解耦和扩展
缺点是性能较低、破坏封装性,因此在业务代码中应谨慎使用
