Java反射机制是运行时动态获取类信息并调用任意方法的核心技术,通过Class、Method等API实现,与Object类无关,仅借助其getClass()获取类型起点。

Object 类本身不提供“动态绑定任意方法”的能力,它只是所有类的根父类。真正实现运行时动态调用任意方法的,是 Java 的反射机制(Reflection),而不是 Object 类的特性。所谓“通过反射动态绑定”,本质是绕过编译期静态检查,在运行时查到类、方法、参数类型,再触发调用——这个过程与 Object 类无关,但所有对象都继承自它,所以反射操作常以 Object 实例为入口。
反射才是动态绑定的执行主体
Java 中没有“Object 类动态绑定方法”这回事。Object 提供的 getClass() 方法只是获取运行时类信息的起点;真正完成方法查找和调用的是 Class、Method 和 invoke() 这套反射 API。
- getClass() 返回当前对象实际类型的 Class 对象,这是反射的第一步,但仅此而已
- 后续必须调用 getDeclaredMethod() 或 getMethod() 才能拿到 Method 实例
- 最终靠 method.invoke(obj, args) 完成调用——这里的 obj 可以是任意对象(包括 Object 子类实例),但 invoke 本身属于 Method 类,不是 Object 的行为
为什么不需要实现接口也能调用任意方法
因为反射跳过了编译期的类型约束和契约校验。接口定义的是“能做什么”的契约,而反射直接操作字节码层面的成员结构:
- 只要类在 JVM 中已加载,且方法可访问(或通过 setAccessible(true) 绕过访问控制),就能被 getMethod() 查到
- invoke() 不关心目标类是否实现某接口,只认方法签名(名称 + 参数类型)和运行时对象的实际类型
- 例如:对一个没实现 Serializable 的类实例,仍可通过反射调用它的 private toString() ——只要它是 Object 的子类(所有类都是),toString() 就天然存在
典型调用链说明
以下代码展示了从普通对象出发,不依赖任何接口,纯靠反射完成方法调用的过程:
立即学习“Java免费学习笔记(深入)”;
- Object obj = new ArrayList<>(); —— 拿到一个 Object 引用,实际是 ArrayList 实例
- Class<?> clz = obj.getClass(); —— 获取真实类型(ArrayList.class)
- Method add = clz.getMethod("add", Object.class); —— 查找 public add 方法
- add.invoke(obj, "hello"); —— 在 obj 上执行,无需 ArrayList 接口声明或转型
整个过程没涉及任何接口实现,也不需要 obj 声明为 ArrayList 或 Collection,纯粹靠运行时元数据驱动。
注意访问权限和性能边界
虽然反射能突破编译期限制,但仍有现实约束:
- private 方法需先调用 method.setAccessible(true),否则抛 IllegalAccessException
- static 方法 invoke 时第一个参数传 null 即可,非 static 则必须传目标实例
- 反射调用比直接调用慢得多(涉及安全检查、参数封装、类型匹配等),不适合高频路径
- JDK 9+ 模块系统下,跨模块访问可能受 ModuleLayer 限制,需显式开放(opens)包
不复杂但容易忽略


















