@override 是编译器检查机制,确保子类方法真正覆盖父类/接口中同名同签名方法;若父类方法为 private/static、签名不匹配、访问权限不足或泛型缺失等,将报错“does not override”。

@Override 不是“用来重写方法”的工具,而是告诉编译器:“我打算覆盖父类中一个同名同签名的方法,请帮我检查是否真能覆盖”。如果父类没这个方法、签名不一致、访问权限不够,编译直接报错——这是它的核心价值。
为什么加了 @Override 还报错“method does not override or implement a method from a supertype”
这是最常见的误用场景:你以为在覆盖,其实根本没对上。
- 父类方法是
private或static——子类里同名方法只是新定义,不是覆盖,加@Override必报错 - 参数类型不一致,比如父类是
String id,你写了Long id,哪怕只差一个包装类,也算重载而非覆盖 - 返回类型不协变(Java 5+ 支持协变返回,但必须是子类型;若父类返回
List,你返回ArrayList可以,但返回String就不行) - 父类方法在另一个包里,且是
protected或包级私有,而子类不在同一包且没继承关系(比如继承错了类,或父类根本没被 import)
在 Spring Boot Service 层覆盖父类 save() 时要注意什么
业务中常见抽象基类封装通用逻辑,子类覆盖特定步骤。但 Spring 的代理机制会让 @Override 表面生效、实际失效。
- 如果父类是
@Service,子类也加了@Service,Spring 默认按类型注入,可能根本没调到你的子类实例 - 若父类方法被
@Transactional修饰,子类覆盖后未显式加该注解,事务边界会丢失(因为代理对象调用的是子类方法,但事务切面没织入) - 不要在覆盖的
save()里直接调super.save()后再处理——除非你确认父类实现可复用;更常见的是调用repository.save()或重构为模板方法模式
IDEA 里自动生成 @Override 方法却漏掉泛型参数怎么办
IntelliJ 在 “Generate → Override Methods” 时,如果父类方法含泛型(如 <t extends user> T process(T input)</t>),默认生成可能丢掉 <t></t> 声明,导致编译失败。
- 手动补全泛型参数:在
public前加上<t extends user></t> - 检查生成后的方法签名是否和父类
javap -s输出的 descriptor 完全一致(尤其是桥接方法存在时) - 启用 IDEA 设置:Settings → Editor → General → Code Completion → 勾选 “Show the full signature for generic methods”
真正容易被忽略的点是:当你在接口实现类里写 @Override,它校验的是接口方法;但在抽象类子类里写,它校验的是抽象类中 abstract 或 default 方法——这两者语义不同,但错误表现一模一样。别只盯着红标,先看清楚你到底在覆盖谁。










