java 反射

Java 反射(Reflection)可以一句话概括为:在运行时"反过来"查看和操作类、方法、字段、构造器等元数据的能力。它是很多框架(Spring、MyBatis、Jackson)的底层基石。

下面用面试 + 实战角度帮你系统梳理。

一、反射能干什么?(核心能力)

能力 示例

运行时获取类信息 类名、修饰符、父类、接口

运行时创建对象 clazz.newInstance() / constructor.newInstance()

运行时调用方法 method.invoke(obj)

运行时读写字段 field.get(obj) / field.set(obj)

绕过访问权限 访问 private 成员

二、获取 Class 对象的三种方式(必会)

// 1. 类名.class(最常用,编译期已知)

Class<?> clazz1 = User.class;

// 2. 对象.getClass()

User user = new User();

Class<?> clazz2 = user.getClass();

// 3. Class.forName()(最灵活,框架最爱)

Class<?> clazz3 = Class.forName("com.example.User");

✅ 区别

• forName:会触发类加载 + 静态代码块

• .class:不会立即初始化

三、反射常用 API(重点)

1️⃣ 构造方法(Constructor)

Constructor ctor =

User.class.getDeclaredConstructor(String.class, int.class);

ctor.setAccessible(true); // 突破 private

User user = ctor.newInstance("Tom", 18);

2️⃣ 字段(Field)

Field field = User.class.getDeclaredField("age");

field.setAccessible(true);

int age = (int) field.get(user);

field.set(user, 20);

3️⃣ 方法(Method)

Method method = User.class.getDeclaredMethod("sayHello", String.class);

method.setAccessible(true);

Object result = method.invoke(user, "World");

四、反射 vs new(面试高频)

对比项 new 反射

编译期检查 ✅ 有 ❌ 无

性能 快 慢(有开销)

灵活性 低 极高

安全性 高 可被绕过

典型场景 普通业务 框架、插件

✅ 结论

• 业务代码:禁止滥用反射

• 框架代码:必须使用反射

五、反射在框架中的真实用途

Spring

• @Autowired:反射注入字段

• @ComponentScan:扫描包 → Class.forName

• AOP:反射 + 动态代理

MyBatis

• 反射读取实体字段 → SQL 映射

• 反射调用 setter / getter

Jackson

• JSON → Java 对象(反射创建 + 赋值)

六、反射的安全与性能问题(重点)

1️⃣ 安全问题

field.setAccessible(true); // 破坏封装

❗ 可能绕过安全检查,甚至修改 final 字段(JDK 9+ 受限)

2️⃣ 性能问题

• 方法调用比直接调用 慢 10~100 倍

• 解决方案:

• 缓存 Method / Field / Constructor

• 使用 sun.misc.Unsafe(极端场景)

• 使用 LambdaMetafactory(Spring 5+)

七、JDK 9 之后的变化(容易被忽略)

• 模块化(JPMS)

• 反射访问非导出包会被拒绝

• 需要 --add-opens

• setAccessible 受限

• 强封装模式下默认禁止

八、反射 + 注解(实战组合)

@Retention(RUNTIME)

@Target(FIELD)

@interface Column {

String value();

}

class User {

@Column("user_name")

private String name;

}

Field field = User.class.getDeclaredField("name");

Column column = field.getAnnotation(Column.class);

System.out.println(column.value()); // user_name

✅ 这是 ORM / 校验框架 的核心原理。

九、面试高频问题(可直接背)

✅ 反射是如何破坏单例的?

→ 通过私有构造器 + setAccessible(true)

✅ 反射为什么慢?

→ 方法查找、权限检查、参数装箱、JVM 优化困难

✅ 如何防止反射攻击单例?

→ 在构造器中判断实例是否已存在并抛异常

✅ 反射和动态代理的关系?

→ 动态代理底层依赖反射调用方法

相关推荐
无限进步_1 小时前
【Linux】进度条:行缓冲区、\r 与 fflush 的实战
linux·服务器·开发语言·数据结构·后端
郝学胜-神的一滴1 小时前
力扣 144:二叉树前序遍历的优雅实现
java·数据结构·c++·python·算法·leetcode·职场和发展
摇滚侠1 小时前
CSDN AI 数字营销测评 专家标注
java
长河1 小时前
APISIX
java·网络
go不是csgo1 小时前
Go-GMP-调度器深度解析(改进版本)
java·linux·golang
轮子飞了1 小时前
基于 Spring AI + Milvus 的 RAG 混合检索实战
java
Evand J1 小时前
【MATLAB程序】基于σ修正自适应律的多无人机菱形编队控制仿真,附下载链接
开发语言·matlab·无人机·控制·编队飞行·多uav
risc1234561 小时前
【Lucene】理解不是看见光,而是让眼睛适应黑暗
java·开发语言
枕星而眠1 小时前
C++面向对象核心:类间关系与继承深度解析
运维·开发语言·c++·后端