最直接有效的方式是靠编译器校验,只要通过@Override注解的编译检查,就说明方法签名、返回类型协变、访问权限不收紧、异常声明不拓宽等四大规则全部满足;编译失败则明确报错,如“method does not override”或“Cannot reduce visibility”。

最直接有效的方式是靠编译器校验,而不是运行时测试——Java 的方法重写是否合规,本质是一个编译期契约问题,不是逻辑正确性问题。只要通过了 @Override 注解的编译检查,就说明签名、返回类型、访问权限、异常声明等全部满足重写规则。
用 @Override 注解强制编译期验证
在子类方法上明确添加 @Override,这是唯一可靠、零成本、静态可验证的方式:
- 如果编译通过 → 表明该方法确实重写了父类(或接口)中某个可重写的方法,所有规则(签名一致、协变返回、权限不收紧、异常不拓宽)均已满足
- 如果编译失败 → 编译器会明确报错,例如:
“method does not override or implement a method from a supertype”(方法名/参数不匹配)
“Cannot reduce the visibility of the inherited method”(访问权限更严格)
“return type is incompatible”(返回类型不协变)
“overridden method does not throw …”(异常声明过宽) - 不要跳过错误去删掉
@Override——那等于放弃校验,把隐患留给运行时
运行时行为验证:多态调用是否生效
编译通过只代表“语法上重写合法”,还需确认“运行时是否真走子类逻辑”。可通过向上转型后调用验证:
- 写一句类似
Parent p = new Child(); p.someMethod(); - 观察输出是否为子类实现的行为(而非父类默认逻辑)
- 配合日志、断点或简单
System.out即可快速验证,无需复杂框架 - 注意:若调用结果仍是父类行为,大概率是没真正重写成功(比如参数类型用了
Object而非String),回头检查@Override是否报错
避免伪测试:不用 JUnit 断言“是否重写”
别写这样的测试:
立即学习“Java免费学习笔记(深入)”;
@Test
void testMethodIsOverridden() {
// ❌ 错误思路:反射检查方法是否存在、是否来自子类……
// 这既不可靠(private/static/final 方法也能“存在”),又绕过了编译契约
// Java 不提供运行时 API 判断“这个方法是否属于重写”,它只在编译期定义什么是重写
}
JUnit 等测试框架适合验证行为是否符合预期(比如 dog.makeSound() 输出 "barks"),但不负责验证语言层面的重写契约——那是编译器的职责。
IDE 辅助与重构安全
现代 IDE(IntelliJ / Eclipse)深度集成重写规则:
- 右键 → “Generate” → “Override Methods…” 会列出所有可重写的方法,生成代码自动带
@Override - 修改父类方法名或参数 → 所有带
@Override的子类方法会立即标红,提示同步更新 - 按住 Ctrl(或 Cmd)点击子类方法名 → “Go to Implementation” 应跳转到自身,“Go to Declaration” 应跳转到父类对应方法


















