一、什么是 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 说明

  1. 构造器getConstructor():获取 public 构造器getDeclaredConstructor():获取任意权限构造器,支持私有构造
  2. 成员变量 FieldgetField():仅获取 public 字段getDeclaredField():获取所有权限字段setAccessible(true):开启暴力反射,无视访问修饰符
  3. 方法 MethodgetMethod():获取 public 方法getDeclaredMethod():获取任意权限方法invoke(对象, 参数):执行目标方法

五、反射优缺点

优点

  1. 极高灵活性:运行期动态创建对象、调用方法,框架必备;
  2. 解耦:配置文件写全类名即可加载类,无需硬编码导入类。

缺点

  1. 性能偏低:绕过编译期优化,动态解析类结构,执行速度慢;
  2. 破坏封装:暴力反射可以读写私有变量、执行私有方法,存在安全隐患;
  3. 代码可读性差,调试难度高于正向编码。

六、典型应用场景

  1. 主流框架底层:Spring IoC 容器、MyBatis、SpringMVC 全部依靠反射实现对象实例化、依赖注入;
  2. 通用工具类:序列化 / 反序列化、JSON 解析工具(FastJSON、Jackson);
  3. 插件化架构:动态加载外部 jar 包里的类,无需重启服务。

七、总结

  1. 反射本质:运行期操纵 Class 元数据,反向操作类的成员;
  2. setAccessible(true)是反射访问私有结构的关键;
  3. 日常业务开发极少手写反射,但所有主流框架底层都重度依赖反射,是 Java 进阶核心知识点。

 

更多推荐