了解java的反射机制
一、什么是反射机制
正常Java开发中,我们在编译阶段就确定要使用的类,通过new关键字直接创建对象、调用方法。而反射是一种逆向操作:程序运行期间,借助类的字节码信息,动态获取类的全部内部结构,还能无差别地创建对象、调用方法、修改成员变量,这种运行时解析操作类的机制,就称为Java反射。
反射的核心依托是Class类。JVM加载每一个类后,都会生成唯一对应的Class对象存储该类完整字节码信息,所有反射操作都必须基于这个Class对象完成。
二、三种获取Class对象的方式
- 类名.class
直接通过静态类标识获取,不会触发类的静态代码块加载,适合已知类名的场景。
Classclazz = User.class; - 对象.getClass()
已有类的实例对象时调用,获取该实例所属类的Class对象。
User user = new User();
Class<?> clazz = user.getClass(); - Class.forName("全限定类名")
通过字符串形式的完整类名加载类并获取Class对象,运行时动态解析,是框架、JDBC中最常用的方式。
Class<?> clazz = Class.forName("com.demo.entity.User");
三、反射核心操作API
依靠Class对象,我们可以操作类的构造器、成员变量、成员方法三大核心结构。 - 操作构造器(Constructor)
通过构造器对象可以创建类实例,即使是私有构造方法也能访问。
getConstructor():获取公有无参/有参构造;
getDeclaredConstructor():获取任意权限构造器(包含private);
newInstance():调用构造器生成对象;
setAccessible(true)`:开启暴力访问,绕过权限校验。 - 操作成员变量(Field)
能够读取、修改对象的属性值,无视private私有修饰符。
getField():获取公有成员变量;
getDeclaredField():获取所有权限成员变量;
get(Object obj):读取指定对象的属性值;
set(Object obj, Object value):修改指定对象的属性值。 - 操作成员方法(Method)
运行时动态调用任意方法,支持私有、带参方法。
getMethod():获取公有方法; getDeclaredMethod():获取所有权限方法;
invoke(Object obj, Object... args)`:执行目标方法,传入实例与参数。
完整基础示例
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("com.demo.entity.User");
// 2. 获取私有无参构造,创建对象
Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Object user = constructor.newInstance();
// 3. 操作私有name属性,赋值
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(user, "张三");
// 4. 调用getName方法获取属性
Method getNameMethod = clazz.getDeclaredMethod("getName");
String name = (String) getNameMethod.invoke(user);
System.out.println(name);
}
}
四、暴力反射:setAccessible(true)
Java的访问修饰符(private、protected)仅在编译阶段做语法限制;运行时通过setAccessible(true)可以关闭权限检查,强行访问私有构造、私有变量、私有方法,这也是反射能够打破面向对象封装特性的关键方法。
五、反射的优缺点
优点
- 动态灵活:无需在编译期绑定类,依靠字符串配置就能动态创建、操作类,适配各类通用框架;
- 框架底层基础:Spring IoC容器、MyBatis持久层、JSON序列化工具、JUnit单元测试全部依靠反射实现核心功能。
缺点
- 性能损耗大:反射需要解析字节码、绕过编译优化,执行速度远低于直接调用代码;
- 破坏封装性:暴力访问私有成员,违背面向对象封装设计思想;
- 代码冗余繁琐:相比直接调用,反射代码量大、可读性差;
- 存在安全隐患:部分安全管理机制会限制反射操作,恶意代码可利用反射篡改私有数据。
六、实际开发应用场景 - JDBC数据库驱动:通过
Class.forName()动态加载不同数据库驱动类; - Spring框架:容器读取配置文件,利用反射创建Bean对象、完成依赖属性注入;
- JSON序列化工具:Jackson、FastJSON通过反射读取实体类字段,实现对象与JSON字符串互转;
- 单元测试JUnit:扫描
@Test注解,反射自动调用测试方法; - 动态代理、配置解析:读取外部配置文件,根据类名字符串动态生成对应业务对象。
七、总结
反射是Java中强大的底层机制,核心价值在于运行时动态操作类,几乎所有主流开发框架都依赖它实现解耦与通用化设计。但在日常业务开发中不建议频繁使用:它性能较差、代码可读性低;仅在开发通用工具、框架组件时,才适合选用反射完成动态化需求。

浙公网安备 33010602011771号