Java多态本身不依赖反射,而是通过JVM虚方法调用动态绑定;反射调用仍遵循多态机制,因getMethod获取实际类型方法,invoke触发虚方法分派,自动执行子类重写逻辑。

Java 中多态本身不依赖反射实现——它是通过 JVM 的虚方法调用(invokevirtual)在运行时动态绑定子类方法的。反射只是另一种调用方式,它绕过了编译期类型检查,但**仍可配合多态机制工作**:只要对象实际是子类实例,用反射调用其继承/重写的方法,JVM 依然会执行子类版本。
反射调用如何体现多态行为
关键在于:反射获取的是 运行时对象的实际类型,而非引用声明类型。只要该对象是子类实例,即使你用父类引用持有它,反射调用重写方法时,仍会触发子类逻辑。
- 用
obj.getClass().getMethod("methodName")获取方法,得到的是该对象真实类中定义或继承的方法(含重写后的方法) - 调用
method.invoke(obj, ...)时,JVM 内部仍走虚方法分派流程,自动选择子类实现 - 不需要手动判断子类类型,也不需要
if (obj instanceof SubClass)分支
一个典型例子
假设:class Animal { void speak() { System.out.println("Animal"); } }
class Dog extends Animal { @Override void speak() { System.out.println("Woof!"); } }
以下代码无论 ref 声明为 Animal 还是 Dog,只要 obj 是 Dog 实例,反射调用就输出 Woof!:
Animal ref = new Dog(); // 多态引用
Method m = ref.getClass().getMethod("speak");
m.invoke(ref); // 输出 Woof! —— 多态生效
注意访问权限和方法可见性
反射调用受 Java 访问控制约束,但可临时绕过:
立即学习“Java免费学习笔记(深入)”;
- 私有方法需先调用
method.setAccessible(true) - 默认(包私有)方法在同包内可直接调用;跨包需
setAccessible(true) - 静态方法用
invoke(null, ...),与多态无关(静态方法不参与多态)
不推荐用反射替代多态设计
反射破坏封装、性能较低、易出 IllegalAccessException/InvocationTargetException,且丧失编译期检查。真正需要多态时,应优先使用:
- 普通方法调用(如
ref.speak()) - 接口或抽象方法定义契约
- 仅在框架、测试、泛型工具等必须解耦类型的场景谨慎使用反射


















