← [ BACK_TO_NOTES ]

Java 反射

反射如何在运行时检查与调用成员:能力、成本、封装绕过与框架使用边界。

#concept #growing #dev #java

[!info] related notes

Java 反射

这个概念为什么出现

框架要在不知道具体类的情况下注入依赖、映射 JSON、调用测试方法。反射提供运行时的类型信息与调用能力,但需要处理访问限制、调用失败和额外开销。

[!abstract] 一句话理解 反射通过 Class/Method/Field 在运行时读取结构并调用;适合框架与工具,不适合业务热路径的默认写法。

最小可运行示例

场景:插件式计算器按方法名调用

import java.lang.reflect.Method;

public class ReflectCall {
    public int add(int a, int b) { return a + b; }

    public static void main(String[] args) throws Exception {
        ReflectCall target = new ReflectCall();
        Method m = ReflectCall.class.getMethod("add", int.class, int.class);
        Object result = m.invoke(target, 2, 3);
        System.out.println(result);
    }
}
javac ReflectCall.java && java ReflectCall

期望:

5

结合场景再看三个关注点

  1. 方法查找按名与参数类型。
  2. 目标方法内部抛出的异常由 invoke 包装为 InvocationTargetException,原因为 getCause();参数不匹配、无访问权限等反射调用错误不属于这种包装。
  3. 模块强封装可能阻止 setAccessible。

核心概念与准确模型

1. 入口

obj.getClass() / Class.forName / .class。单参数 Class.forName(name) 会初始化目标类;类字面量本身不触发初始化,Class.forName(name, false, loader) 可请求不初始化。

2. 成员访问

getMethod 查 public 方法(含继承);getDeclaredMethod 仅查本类声明(含非 public),查到不等于有权调用。查找要求参数类型匹配,不会把 Integer.class 自动当作 int.class;invoke 则支持规定的拆箱和基本类型拓宽转换。

3. 代价

  • 动态查找、参数包装与访问检查可能带来额外成本;JIT 优化和缓存效果依赖 JDK 与调用方式,不能断言反射一律无法优化。
  • 安全与封装风险

边界情况与反直觉行为

  1. 泛型擦除使反射拿不到完整运行时参数类型。
  2. 基本类型与包装类型在 Class 字面量上不同。
  3. Native Image 中无法静态推导的反射访问可能需要可达性元数据;不能照搬普通 JVM 的动态发现假设。

常见误区

[!warning] 常见误区:业务代码遍地反射 优先接口多态与生成代码。

工程实践

  1. 反射集中在框架边界,必要时缓存 Method 对象以避免重复查找。
  2. 可评估 MethodHandle,但它与 Method 是不同 API,性能应实测。
  3. exports 允许对导出包的 public 类型和成员进行通常访问;跨模块访问非公开成员通常需要目标包 opens。
  4. setAccessible(true) 不能任意突破模块封装,可能抛 InaccessibleObjectException;可用 trySetAccessible() 判断是否能开放访问。

本节总结

  • 运行时元编程利器
  • 成本与封装代价
  • 框架常用、业务慎用

自测题

  1. getMethod 与 getDeclaredMethod 差别?
  2. 为什么 JSON 库爱反射或代码生成?
参考答案
  1. 前者看 public 成员(含继承);后者看本类声明成员含非 public。
  2. 需要在未知类型上读写属性;生成代码可降运行时成本。

延伸阅读与资料来源

资料类型支撑内容
Reflection Trail教程反射
java.lang.reflectAPI包
创建于 2026/7/15 更新于 2026/10/6
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本