一、反射是什么?(通俗理解)
反射是Java提供的一种机制,允许程序在运行时(而不是编译时):
1.获取任意类的完整信息(类名、属性、方法、构造器、继承关系等)
2.操作任意对象的属性和方法(即使是private修饰的)
3.动态创建对象、调用方法,无需提前知道类的具体名称
定义
Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法 ;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制 。
可以把反射理解为:程序自己 "审视" 和 "操作" 自己的能力。就像一个人能看清自己的身体结构,还能手动控制自己的器官运作。
反射最重要的用途就是开发各种通用框架
二、反射的核心类(都在java.lang.reflect包下)

三、反射的基本使用步骤(实战示例)
先定义一个普通的测试类,后续用反射操作它:
java
public class Student {
// 私有属性
private String name;
// 公有属性
public int age;
// 无参构造
public Student() {}
// 有参构造
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// 私有方法
private String sayHello(String msg) {
return name + "说:" + msg;
}
// 公有方法
public void showInfo() {
System.out.println("姓名:" + name + ",年龄:" + age);
}
// getter/setter(省略,后面会用反射操作name)
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
步骤 1:获取 Class 对象(反射的入口)
获取Class对象有 3 种方式:
java
public class ReflectionDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 方式1:通过类名.class(编译时已知类)
Class<Student> clazz1 = Student.class;
// 方式2:通过对象.getClass()(已有对象)
Student student = new Student();
Class<? extends Student> clazz2 = student.getClass();
// 方式3:通过Class.forName("全类名")(运行时动态获取,最灵活)
Class<?> clazz3 = Class.forName("com.example.Student");
// 验证:三个Class对象是同一个(JVM中每个类只有一个Class实例)
System.out.println(clazz1 == clazz2); // true
System.out.println(clazz1 == clazz3); // true
}
}
步骤 2:通过反射创建对象
java
// 1. 调用无参构造创建对象
Class<?> clazz = Class.forName("com.example.Student");
Student s1 = (Student) clazz.newInstance(); // 旧方式(JDK9后标记为过时)
// 推荐方式:通过Constructor调用无参构造
Constructor<?> constructor = clazz.getConstructor();
Student s1 = (Student) constructor.newInstance();
// 2. 调用有参构造创建对象
Constructor<?> constructor2 = clazz.getConstructor(String.class, int.class);
Student s2 = (Student) constructor2.newInstance("张三", 18);
s2.showInfo(); // 输出:姓名:张三,年龄:18
步骤 3:通过反射操作属性(包括私有属性)
java
// 1. 获取并修改公有属性age
Field ageField = clazz.getField("age");
ageField.set(s2, 20); // 给s2的age赋值20
System.out.println(ageField.get(s2)); // 输出20
// 2. 获取并修改私有属性name(需要先设置可访问)
Field nameField = clazz.getDeclaredField("name"); // getDeclaredField能获取所有修饰符的属性
nameField.setAccessible(true); // 关闭访问检查(突破private限制)
nameField.set(s2, "李四");
System.out.println(nameField.get(s2)); // 输出李四
步骤 4:通过反射调用方法(包括私有方法)
java
// 1. 调用公有方法showInfo
Method showInfoMethod = clazz.getMethod("showInfo");
showInfoMethod.invoke(s2); // 输出:姓名:李四,年龄:20
// 2. 调用私有方法sayHello
Method sayHelloMethod = clazz.getDeclaredMethod("sayHello", String.class);
sayHelloMethod.setAccessible(true); // 关闭访问检查
String result = (String) sayHelloMethod.invoke(s2, "你好!");
System.out.println(result); // 输出:李四说:你好!
四、反射的应用场景
- 框架核心:Spring、MyBatis、Hibernate等框架大量使用反射(比如 Spring的IOC容器动态创建 Bean,MyBatis的结果集映射)。
- 动态代理:AOP(面向切面编程)的底层实现依赖反射。
- 工具类:比如JSON序列化/反序列化工具(FastJSON、Jackson),通过反射读取对象属性并转为JSON。
- 插件/扩展开发:运行时动态加载外部类并调用其方法。
五、反射的优缺点

总结
1.核心本质 :反射是Java程序在运行时获取类信息、操作对象的机制,核心入口是c1ass类。
2.关键操作 :获取class对象→创建对象→操作属性/方法(私有成员需设置setAccessible(true))。
3.核心价值:是框架的基础,实现"动态编程",但日常开发中应尽量少用(避免性能和封装性问题)。
反射本身不属于"数据结构",但它是Java高级编程的核心,常和集合、泛型等数据结构结合使用,掌握它能帮你理解框架的底层逻辑