判断子类是否真正重写父类方法,需综合继承链、语义及字节码:运行时通过父类引用调用并观察执行逻辑;反射检查getdeclaringclass()与isbridge();并校验private/static/final限制、签名一致性、访问权限和异常声明等前提。

检测子类是否真正重写了父类方法,不能只看方法名和签名是否一致——Java 的类型擦除、桥接方法(bridge method)、访问修饰符限制等都会干扰判断。核心在于:**必须结合继承链 + 方法语义 + 字节码特征来验证覆盖行为是否生效**。
看方法是否在运行时被多态调用
覆盖的本质是多态分派:当通过父类引用调用方法时,JVM 实际执行的是子类中重写后的方法。因此最可靠的验证方式是运行时观察行为:
- 构造父类类型引用指向子类实例,例如 Parent p = new Child();
- 调用该方法,检查执行的是父类体还是子类体(可通过日志、断点或返回值差异确认)
- 若执行子类逻辑,说明覆盖已生效;若仍走父类体,可能是方法未被正确覆盖(如 static、private、final,或签名不匹配)
用反射比对方法的声明类与实际归属
反射可读取 Method.getDeclaringClass(),这是关键线索:
- 若子类中声明的方法,其 getDeclaringClass() == Child.class,且父类存在同签名方法 → 极可能已覆盖
- 若子类方法的 getDeclaringClass() == Parent.class,说明该方法来自继承,未被重写
- 注意桥接方法:泛型擦除后生成的
doStuff(Object)可能声明类是子类,但它是编译器插入的转发器,真实逻辑仍在doStuff(String)中 → 需结合 Method.isBridge() 排除
检查覆盖前提是否满足(静态校验)
在反射遍历前,先人工/程序化验证以下硬性条件,任一不满足即不可能覆盖:
- 父类方法不能是 private、static 或 final
- 子类方法名、参数类型(擦除后)、返回类型(协变允许)必须与父类一致
- 子类方法访问权限不能比父类更严格(如父类
protected,子类不能用private) - 异常声明不能扩大(子类方法抛出的受检异常不能多于父类)
避免常见误判场景
这些情况看似“重写”,实则不是真正的覆盖:
- 重载(Overload):同一类中参数不同 → 与继承无关,反射中属于不同 Method 对象
- 隐藏(Hiding):子类定义了与父类 static 方法同名同参的方法 → 不是覆盖,而是静态绑定
- 桥接方法:编译器自动生成的转发方法(isBridge() == true)→ 它存在只为支持泛型多态,不应视为业务层“重写”
-
默认方法冲突:实现多个接口时,若接口默认方法签名相同,需显式重写,否则编译报错 → 反射中会看到子类声明的方法,但需确认是否带
@Override或显式实现










