反射不直接实现多态,但通过运行时真实类型调用覆盖方法,体现动态绑定本质:getMethod() 查找最具体可访问方法,invoke() 依实例实际类型执行子类逻辑。

反射本身不直接参与多态机制,但能配合多态行为,在运行时调用实际对象类型所覆盖的方法——关键在于:反射调用的是对象**运行时的真实类型**上的方法,而非声明类型,这与多态的动态绑定本质一致。
反射调用覆盖方法的前提条件
要让反射正确调用子类覆盖(override)的方法,必须满足以下三点:
- 目标方法是 public 或 protected 的实例方法(不能是 private 或 static);
- 反射调用时传入的是子类的实际实例(例如
new Dog()而非Animal a = new Dog()后仅用a); - 使用
getMethod()获取方法(它会沿继承链向上查找,返回最具体的可访问实现)。
为什么 getMethod() 能体现多态
getMethod(String name, Class...) 返回的是该 Class 对象所表示类型及其父类中可访问的、签名匹配的最具体方法。当对子类实例调用时,即使通过父类 Class 获取 Method,只要该 Method 在子类中被覆盖,invoke() 执行时仍会触发 JVM 的动态分派,最终执行子类重写的逻辑。
例如:
class Animal { public void speak() { System.out.println("Animal speaks"); } }
class Dog extends Animal { @Override public void speak() { System.out.println("Woof!"); } }
Animal dog = new Dog();
Class<?> clazz = Animal.class;
Method method = clazz.getMethod("speak");
method.invoke(dog); // 输出 "Woof!",不是 "Animal speaks"
这里虽然用 Animal.class 获取方法,但 invoke(dog) 中的 dog 是 Dog 实例,JVM 在运行时根据实际类型选择方法实现 —— 这正是多态的核心。
避免常见误区:getDeclaredMethod 不适用
getDeclaredMethod() 只在当前类中查找,不搜索父类,因此:
- 若用
Dog.class.getDeclaredMethod("speak"),能拿到Dog的覆盖版本; - 但若用
Animal.class.getDeclaredMethod("speak"),它只返回Animal自身定义的方法,而invoke(new Dog())依然会执行Dog.speak()—— 因为多态由对象实例决定,不是由 Method 对象来源决定; - 不过若方法在子类中是
private,则无法被覆盖(private 方法不可继承),此时不存在多态,反射也拿不到子类版本。
实用建议:保持反射与多态协同
想稳妥利用反射调用覆盖方法,推荐做法:
- 始终用
obj.getClass().getMethod(...)获取 Method,确保从实际类型出发; - 直接传入子类实例(而非父类引用)给
invoke(),避免混淆; - 无需手动判断是否覆盖 —— JVM 自动完成动态绑定,反射只是触发它的载体;
- 若需强制调用父类原始实现(绕过多态),只能通过
Method.setAccessible(true)配合反射父类的私有/包级方法(不推荐,破坏封装且非常规)。

















