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 优化困难

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

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

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

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

相关推荐
江畔柳前堤4 小时前
roLabelImg 详细安装教程
开发语言·人工智能·后端·云原生
Wang's Blog5 小时前
Go-Zero 项目开发47:自研微服务框架的必要性与核心结构设计
开发语言·微服务·golang
白鸽(二般)5 小时前
MinIO Java Client API
java·开发语言
hPw0eKIqD5 小时前
C++ 模板参数推导问题小记(非推导上下文)
开发语言·c++
临床数据科学和人工智能兴趣组5 小时前
要使用 R Markdown,首先需要安装 R 和 RStudio,接着安装 rmarkdown 包
开发语言·数据挖掘·数据分析·r语言·r语言-4.2.1
软萌萌的16 小时前
Java Spring Boot 修改yml配置&加载顺序规则
java·spring boot·python
Nebula嵌入式6 小时前
【C语言】09-深入解析main函数
linux·c语言·开发语言·嵌入式
IT小盘6 小时前
13-企业Prompt模板-角色任务约束与输出格式
java·前端·prompt
爱敲键盘的猴子7 小时前
Java并发编程 -- volatile
java·java并发
神罚天下ET8 小时前
c# ACME client (补充)
开发语言·c#