一、什么是 Java 反射机制
Java 反射机制:在程序运行阶段,动态获取类的完整结构(类名、属性、方法、构造器),并可以实例化对象、调用任意方法、读写成员变量,这种动态操作类信息的能力就叫反射。
正常编码是new 类名()正向创建对象,编译期就确定类型;反射是运行期才解析类结构,实现解耦、框架底层核心支撑。
二、反射核心:Class 类对象
每一个 Java 类加载后,JVM 都会生成唯一对应的Class对象,这个对象存储了当前类全部元信息,反射所有操作都基于该Class对象展开。
获取 Class 对象 3 种方式:
// 方式1:类名.class(编译期获取) Class<User> clazz1 = User.class; // 方式2:对象.getClass()(已有实例对象) User user = new User(); Class<? extends User> clazz2 = user.getClass(); // 方式3:Class.forName("全类名")(最常用,框架配置文件加载类) Class<?> clazz3 = Class.forName("com.demo.User");三、完整实战代码
1. 实体类准备
public class User { // 私有成员变量 private String username; public Integer age; // 无参构造 public User() {} // 有参构造 public User(String username, Integer age) { this.username = username; this.age = age; } // 私有方法 private void showPrivateMsg(String msg) { System.out.println("私有方法执行:" + msg); } // 公共方法 public void sayHello() { System.out.println("Hello 反射"); } // getter/setter public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }2. 反射全套操作示例
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectDemo { public static void main(String[] args) throws Exception { // 1. 获取Class对象 Class<?> clazz = Class.forName("User"); // 2. 反射调用构造器,实例化对象 Constructor<?> con = clazz.getDeclaredConstructor(String.class, Integer.class); User user = (User) con.newInstance("张三", 20); System.out.println("实例化对象:" + user.getUsername()); // 3. 反射操作私有成员变量 Field nameField = clazz.getDeclaredField("username"); nameField.setAccessible(true); // 暴力反射,破除private权限 nameField.set(user, "李四"); System.out.println("修改后用户名:" + nameField.get(user)); // 4. 反射调用私有方法 Method privateMethod = clazz.getDeclaredMethod("showPrivateMsg", String.class); privateMethod.setAccessible(true); privateMethod.invoke(user, "反射可以执行私有方法"); // 5. 反射调用公共方法 Method publicMethod = clazz.getMethod("sayHello"); publicMethod.invoke(user); } }四、关键 API 说明
- 构造器
getConstructor():获取 public 构造器getDeclaredConstructor():获取任意权限构造器,支持私有构造 - 成员变量 Field
getField():仅获取 public 字段getDeclaredField():获取所有权限字段setAccessible(true):开启暴力反射,无视访问修饰符 - 方法 Method
getMethod():获取 public 方法getDeclaredMethod():获取任意权限方法invoke(对象, 参数):执行目标方法
五、反射优缺点
优点
- 极高灵活性:运行期动态创建对象、调用方法,框架必备;
- 解耦:配置文件写全类名即可加载类,无需硬编码导入类。
缺点
- 性能偏低:绕过编译期优化,动态解析类结构,执行速度慢;
- 破坏封装:暴力反射可以读写私有变量、执行私有方法,存在安全隐患;
- 代码可读性差,调试难度高于正向编码。
六、典型应用场景
- 主流框架底层:Spring IoC 容器、MyBatis、SpringMVC 全部依靠反射实现对象实例化、依赖注入;
- 通用工具类:序列化 / 反序列化、JSON 解析工具(FastJSON、Jackson);
- 插件化架构:动态加载外部 jar 包里的类,无需重启服务。
七、总结
- 反射本质:运行期操纵 Class 元数据,反向操作类的成员;
setAccessible(true)是反射访问私有结构的关键;- 日常业务开发极少手写反射,但所有主流框架底层都重度依赖反射,是 Java 进阶核心知识点。