Java 反射机制详解:从基础到实战,彻底掌握 Class、Method、Field 的动态操作
作为一名 Java 开发工程师,你可能已经听说过“反射”(Reflection)这个词,也一定在使用 Spring、Hibernate、MyBatis 等框架时感受到它的强大。反射是 Java 语言中最强大、最灵活的特性之一,它允许我们在运行时动态地获取类的信息、调用方法、访问属性,甚至创建对象。
本文将带你全面掌握:
- 什么是反射?
- 反射的核心类(Class、Method、Field、Constructor)
- 如何通过反射动态操作类与对象
- 使用反射实现通用工具类、工厂模式、注解解析等
- 反射的优缺点与性能优化
- 反射在主流框架中的应用(Spring、MyBatis 等)
并通过丰富的代码示例和真实项目场景讲解,帮助你写出更灵活、更通用、更高级的 Java 代码。
🧱 一、什么是反射(Reflection)?
✅ 反射定义:
反射是 Java 提供的一种机制,它允许程序在**运行时(Runtime)**动态地获取类的信息(如类名、方法、属性等),并可以操作类或对象的内部结构。
✅ 反射的作用:
🧠 二、反射的核心类与接口
反射的核心类都位于 java.lang.reflect
包中:
Class
Object
Method
Field
Constructor
Modifier
Annotation
🧪 三、反射的基本使用
✅ 1. 获取 Class 对象的三种方式
// 方式一:通过类名.class 获取Class clazz1 = String.class;// 方式二:通过对象.getClass() 获取String str = \"hello\";Class clazz2 = str.getClass();// 方式三:通过 Class.forName(\"全限定类名\") 获取Class clazz3 = Class.forName(\"java.util.ArrayList\");
✅ 2. 动态创建对象(newInstance)
// 获取 Class 对象Class clazz = Class.forName(\"com.example.User\");// 创建对象(调用无参构造方法)Object obj = clazz.newInstance();// 或者使用 Constructor 创建(可调用有参构造)Constructor constructor = clazz.getConstructor(String.class, int.class);Object user = constructor.newInstance(\"Tom\", 25);
✅ 3. 动态调用方法(invoke)
// 获取方法Method method = clazz.getMethod(\"sayHello\", String.class);// 调用方法method.invoke(obj, \"反射你好!\");
✅ 4. 动态访问字段(get/set)
// 获取字段Field field = clazz.getDeclaredField(\"name\");// 设置可访问(突破 private 限制)field.setAccessible(true);// 设置字段值field.set(obj, \"Jerry\");// 获取字段值Object value = field.get(obj);System.out.println(value); // 输出 Jerry
🧩 四、反射的高级用法
✅ 1. 获取类的全部方法和字段
Method[] methods = clazz.getDeclaredMethods();for (Method m : methods) { System.out.println(\"方法名:\" + m.getName());}Field[] fields = clazz.getDeclaredFields();for (Field f : fields) { System.out.println(\"字段名:\" + f.getName());}
✅ 2. 使用反射实现通用工厂模式
public class BeanFactory { public static T createBean(String className) { try { Class clazz = Class.forName(className); return (T) clazz.newInstance(); } catch (Exception e) { throw new RuntimeException(\"创建对象失败\", e); } }}
✅ 3. 反射 + 注解:实现自定义注解处理器
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface MyAnnotation { String value();}// 使用注解public class MyClass { @MyAnnotation(\"Hello\") public void myMethod() { System.out.println(\"执行方法\"); }}// 反射解析注解public class AnnotationProcessor { public static void process(Object obj) throws Exception { for (Method method : obj.getClass().getDeclaredMethods()) { if (method.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation anno = method.getAnnotation(MyAnnotation.class); System.out.println(\"注解值:\" + anno.value()); method.invoke(obj); // 执行带注解的方法 } } }}
🧪 五、反射在主流框架中的应用
✅ 1. Spring IOC 容器(依赖注入)
Spring 通过反射自动创建 Bean、注入依赖、调用方法。
// Spring 内部实现类似逻辑Class clazz = Class.forName(\"com.example.MyService\");Object service = clazz.newInstance();field.setAccessible(true);field.set(controller, service); // 注入依赖
✅ 2. MyBatis ORM 框架
MyBatis 利用反射将数据库结果集自动映射到 Java 对象。
// 伪代码Object user = clazz.newInstance();Field idField = clazz.getDeclaredField(\"id\");idField.setAccessible(true);idField.set(user, resultSet.getInt(\"id\"));
✅ 3. JSON 序列化/反序列化(如 Jackson、Gson)
通过反射读取字段名和值,实现对象与 JSON 的互转。
public static String toJson(Object obj) throws Exception { Class clazz = obj.getClass(); StringBuilder sb = new StringBuilder(\"{\"); for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); sb.append(\"\\\"\").append(field.getName()).append(\"\\\":\\\"\").append(field.get(obj)).append(\"\\\",\"); } sb.deleteCharAt(sb.length() - 1).append(\"}\"); return sb.toString();}
⚠️ 六、反射的优缺点与性能优化
✅ 优点:
❌ 缺点:
✅ 性能优化建议:
MethodHandle
或 VarHandle
(JDK 7+)替代反射🧱 七、反射最佳实践
setAccessible(true)
突破访问限制🚫 八、常见误区与注意事项
IllegalAccessException
、InvocationTargetException
等setAccessible(true)
📊 九、总结:Java 反射核心知识点一览表
Class
、Method
、Field
、Constructor
.class
、.getClass()
、Class.forName()
newInstance()
、Constructor.newInstance()
Method.invoke()
Field.get()
、Field.set()
isAnnotationPresent()
、getAnnotation()
📎 十、附录:Java 反射常用技巧速查表
clazz.getName()
clazz.getDeclaredMethods()
clazz.getDeclaredFields()
clazz.getConstructor(Class...)
clazz.newInstance()
method.invoke(obj, args)
field.set(obj, value)
field.setAccessible(true)
method.getAnnotation(MyAnnotation.class)
method.isAnnotationPresent(MyAnnotation.class)
欢迎点赞、收藏、转发,也欢迎留言交流你在实际项目中遇到的反射相关问题。我们下期再见 👋
📌 关注我,获取更多Java核心技术深度解析!