Java 反射(Reflection)完整讲解

一、什么是反射

反射机制:程序运行时,动态获取类的全部信息(类名、成员变量、方法、构造器),并调用对象方法、操作属性。
正常开发:编译期就确定类、方法,直接 new 对象() 调用;
反射:运行时才解析类,无需提前硬编码。

二、反射核心类(java.lang.reflect)

  1. Class:代表类/接口的字节码对象,反射入口
  2. Constructor:构造方法
  3. Method:成员方法
  4. Field:成员变量

三、获取 Class 对象的三种方式

// 1. 对象.getClass()(已有实例)
Person p = new Person();
Class<?> clazz1 = p.getClass();

// 2. 类名.class(静态获取,推荐)
Class<?> clazz2 = Person.class;

// 3. Class.forName("全类名")(最常用,配置文件加载类)
Class<?> clazz3 = Class.forName("com.test.Person");

四、反射操作全流程示例

实体类

public class Person {
    public String name;
    private int age;

    // 无参构造
    public Person(){}
    // 私有有参构造
    private Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 公有方法
    public void show(String msg) {
        System.out.println("show:" + msg);
    }
    // 私有方法
    private void secret() {
        System.out.println("私有方法");
    }
}

1. 通过反射创建对象

Class<?> clazz = Person.class;

// 1)无参构造创建对象
Object obj1 = clazz.newInstance(); // JDK9+废弃,推荐Constructor

// 标准写法
Constructor<?> con1 = clazz.getConstructor();
Person p1 = (Person) con1.newInstance();

// 2)获取私有构造,暴力访问
Constructor<?> con2 = clazz.getDeclaredConstructor(String.class, int.class);
con2.setAccessible(true); // 关闭权限校验
Person p2 = (Person) con2.newInstance("张三", 20);

2. 反射操作成员变量 Field

Person p = new Person();
Class<?> clazz = p.getClass();

// 获取公有变量
Field nameField = clazz.getField("name");
nameField.set(p, "李四");
System.out.println(nameField.get(p));

// 获取私有变量
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(p, 18);
System.out.println(ageField.get(p));

3. 反射调用方法 Method

Person p = new Person();
Class<?> clazz = p.getClass();

// 公有方法
Method show = clazz.getMethod("show", String.class);
show.invoke(p, "测试消息");

// 私有方法
Method secret = clazz.getDeclaredMethod("secret");
secret.setAccessible(true);
secret.invoke(p);

五、关键方法区分

  1. getXXX():只获取public(父类公有也能拿到)
    • getField / getMethod / getConstructor
  2. getDeclaredXXX():获取本类所有(public/private/protected),不包含父类
    • getDeclaredField / getDeclaredMethod / getDeclaredConstructor

六、setAccessible(true) 暴力反射

私有构造、私有变量、私有方法默认无法访问;
setAccessible(true) 关闭Java权限检查,运行时强行操作私有成员。

七、反射优缺点

优点

  1. 高度灵活:运行时动态创建对象、调用方法,框架底层核心(Spring、Mybatis)
  2. 解耦:通过配置文件全类名加载类,不用硬编码 new

缺点

  1. 性能差:绕过编译期优化,执行速度慢
  2. 破坏封装:暴力访问私有属性/方法,违背面向对象封装
  3. 安全性问题:可绕过权限校验,部分高安全环境禁用反射
  4. 代码繁琐,可读性差

八、反射典型应用场景

  1. Spring IoC:通过反射创建Bean、注入属性
  2. ORM框架(Mybatis):反射映射数据库字段与实体属性
  3. 注解解析、动态代理
  4. 配置文件读取类,动态实例化
  5. 单元测试框架JUnit动态调用测试方法

九、面试核心考点

  1. 获取Class对象三种方式区别
  2. getXXX 和 getDeclaredXXX 的区别
  3. setAccessible(true)作用
  4. 反射优缺点
  5. 反射为什么性能低
  6. 反射破坏封装的体现
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐