一、定义
Java 反射机制,是指在程序运行期间,对任意一个类,都能知道它的所有属性和方法;对任意一个对象,都能调用它的任意方法和属性。
简单说:
- 正常开发中,我们是 "先有类,再用对象调用方法 / 属性",编译期就确定了。
- 反射是 "运行时动态获取类的信息、创建对象、调用方法",甚至能直接操作
private修饰的私有成员。
一句话总结:反射就是运行时动态解剖、操作类的所有资源。
反射是很多框架的底层基础,比如 Spring 的 IOC、MyBatis 的动态代理、ORM 框架的对象映射,核心都是反射。
二、示例
定义测试实体类
public class Animal {
// 四种访问权限成员变量
private String name = "animal";
public String sex = "男";
Integer age = 18;
protected String color = "黑色";
// 三种权限构造方法
public Animal() {
System.out.println("无参构造");
}
// 私有构造方法
private Animal(String name) {
System.out.println("私有有参构造");
}
// 默认权限构造方法
Animal(String name, int age) {
System.out.println("默认权限有参构造");
}
// 普通公有方法
public void show() {
System.out.println("public 方法 show()");
}
// 私有方法
private void fly() {
System.out.println("私有方法 fly()");
}
}
Class是所有反射操作的唯一入口!!!
获取Class对象的三种方式
public class ReflectTest {
public static void main(String[] args) throws ClassNotFoundException {
// 方式1:Class.forName("全类名") 【框架最常用】
Class<?> clazz1 = Class.forName("Animal");
// 方式2:类名.class 【静态获取,简单高效】
Class<Animal> clazz2 = Animal.class;
// 方式3:对象.getClass() 【已有对象实例时使用】
Animal animal = new Animal();
Class<? extends Animal> clazz3 = animal.getClass();
// 验证:三个方式获取的是同一个对象
System.out.println(clazz1 == clazz2); // true
System.out.println(clazz1 == clazz3); // true
}
}
| 获取方式 | 核心特点 | 适用场景 |
|---|---|---|
| Class.forName() | 动态加载类,需要捕获异常 | 读取配置文件、框架动态加载类 |
| 类名.class | 静态获取,无异常,性能高 | 普通工具类、固定类操作场景 |
| 对象.getClass() | 基于已有对象反向获取类信息 | 运行时动态判断对象类型 |
三、反射核心API:获取类的所有资源

面试一句话秒杀答案: 带 Declared 只看本类、全包权限;不带 Declared 只看 Public、含父类。
2. 暴力反射 setAccessible(true) 细节
很多同学以为开启暴力反射是"修改权限",其实是误区:
2. 反射中的致命坑点
如果实体类中同时存在 int age 和 Integer age,反射表现完全不同:
注意:private 资源不开启该方法,直接反射操作会直接报错权限不足。
1. getXXX 和 getDeclaredXXX 区别
-
getFields() / getMethods() / getConstructors() 只获取 public 修饰的资源,包含父类继承的公共资源,无法获取本类私有、默认、受保护资源。
-
getDeclaredFields() / getDeclaredMethods() / getDeclaredConstructors() 获取本类中所有权限 的资源(public/protected/default/private),不获取父类任何资源。
-
不会修改源码权限修饰符
-
只是关闭 Java 语法权限校验
-
仅在本次反射操作有效,运行结束恢复原有权限规则
-
int :基本数据类型,默认值 0 ,不能为 null,栈内存存储,不属于对象
-
Integer :包装类对象,默认值 null ,可以为空,堆内存存储
-
反射获取 int 类型字段:永远不会空,未赋值默认返回 0
-
反射获取 Integer 类型字段:未赋值默认返回 null,直接调用方法会空指针

四、完整测试代码
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) throws Exception {
// 1. 获取Class对象
Class<?> clazz = Class.forName("Animal");
Animal animal = new Animal();
// 2. 获取所有成员变量
System.out.println("==========所有成员变量==========");
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
// 3. 获取所有成员方法
System.out.println("==========所有成员方法==========");
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
// 4. 获取所有构造方法
System.out.println("==========所有构造方法==========");
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
// 5. 暴力反射操作私有变量
System.out.println("==========暴力反射操作私有资源==========");
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(animal, "小狗");
System.out.println("修改后的私有属性:" + nameField.get(animal));
// 调用私有方法
Method flyMethod = clazz.getDeclaredMethod("fly");
flyMethod.setAccessible(true);
flyMethod.invoke(animal);
}
}
五、作业

5.1student.java
public class Student {
// 私有属性
private String name;
private final Integer stuId;
private static String school;
// 有参构造
public Student(String name, Integer stuId) {
this.name = name;
this.stuId = stuId;
}
// 私有无参构造(私有化)
private Student() {
this.stuId = 0; // final属性必须在构造器中初始化
}
// 普通公有方法
public void publicMethod() {
System.out.println("这是一个普通的公有成员方法");
}
// 私有自定义方法
private void privateMethod(String message) {
System.out.println("这是私有方法,收到消息:" + message);
}
// 静态方法
public static void staticMethod() {
System.out.println("这是一个静态方法");
}
// 为了方便看结果,重写toString
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", stuId=" + stuId +
", school='" + school + '\'' +
'}';
}
}
5.2 test.java
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectionTest {
public static void main(String[] args) throws Exception {
// 1. 获取Class对象
Class<Student> studentClass = Student.class;
// 2. 破解私有无参构造,创建实例
Constructor<Student> privateConstructor = studentClass.getDeclaredConstructor();
// 暴力反射:关闭访问检查
privateConstructor.setAccessible(true);
Student student = privateConstructor.newInstance();
System.out.println("创建的实例:" + student);
// 3. 给普通私有属性赋值、读取
Field nameField = studentClass.getDeclaredField("name");
nameField.setAccessible(true);
// 赋值
nameField.set(student, "张三");
// 读取
String nameValue = (String) nameField.get(student);
System.out.println("name属性值:" + nameValue);
// 4. 修改final修饰的私有常量属性(进阶考点)
Field stuIdField = studentClass.getDeclaredField("stuId");
stuIdField.setAccessible(true);
// 先去掉final的修饰(反射修改的关键步骤)
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(stuIdField, stuIdField.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
// 修改值
stuIdField.set(student, 1001);
Integer stuIdValue = (Integer) stuIdField.get(student);
System.out.println("stuId(final属性)修改后的值:" + stuIdValue);
// 5. 修改/获取static静态私有属性
Field schoolField = studentClass.getDeclaredField("school");
schoolField.setAccessible(true);
// 静态属性,obj传null即可
schoolField.set(null, "中移铁通大学");
String schoolValue = (String) schoolField.get(null);
System.out.println("school(static属性)的值:" + schoolValue);
// 6. 调用私有成员方法、静态私有方法
// 调用私有成员方法
Method privateMethod = studentClass.getDeclaredMethod("privateMethod", String.class);
privateMethod.setAccessible(true);
privateMethod.invoke(student, "反射调用成功!");
// 调用公有静态方法(这里题目里的静态方法是公有的,也可以写一个私有的静态方法演示)
Method staticMethod = studentClass.getDeclaredMethod("staticMethod");
staticMethod.setAccessible(true);
staticMethod.invoke(null); // 静态方法,obj传null
// 最终查看对象状态
System.out.println("最终Student对象状态:" + student);
}
}
