@Override仅检查方法是否真正重写父类或接口方法,若方法名、参数类型、顺序、返回类型(协变除外)或泛型擦除后不一致即报错,它不参与运行时多态,纯编译期防错机制。

为什么加了 @Override 还报错“method does not override or implement a method from a supertype”
这是最常见的误解:以为只要写了 @Override,编译器就会自动帮你对齐父类方法签名。实际上,它只做一件事——检查当前方法是否**确实重写了父类或接口中已声明的方法**。如果方法名、参数类型、参数顺序、返回类型(协变除外)甚至泛型擦除后不一致,它就直接报错。
常见错误现象:
- 父类方法是
public void process(String s),子类写成public void process(Object s)—— 参数类型不同,不算重写 - 父类方法返回
List,子类返回ArrayList—— 这倒可以(协变返回),但若写成String就不行 - 父类方法是
default void log()(接口默认方法),子类用private void log()重写 —— 访问修饰符不能比父类更严格 - 拼错方法名,比如把
toString()写成toStirng(),@Override会立刻揪出
@Override 在接口实现时到底管不管用
管,而且非常关键。Java 6 开始,@Override 就支持标注对接口方法的实现(不只是继承类)。但前提是:接口方法必须是 public abstract 的(包括 default/static 以外的所有接口方法)。
使用场景:
立即学习“Java免费学习笔记(深入)”;
- 实现
Comparable时写public int compareTo(T o),漏了@Override可能导致排序逻辑完全不生效(因为方法没被识别为重写) - 重写
Runnable.run()或Callable.call(),不加@Override时改错签名也不会报警 - 接口升级新增 default 方法,你本想重写它,却因签名微小差异(如多了一个
final参数)而实际没重写成功
注意:@Override 对 static 方法无效——静态方法无法被重写,只能被隐藏,加了会编译失败。
IDE 自动补全加了 @Override,但运行时行为没变,是不是没起作用
起作用了,只是它的作用发生在编译期,不是运行期。它不改变字节码、不提升性能、也不影响多态分派逻辑。它的价值纯粹是“防手抖”。
容易踩的坑:
- 把
@Override当成“启用多态”的开关——其实只要方法签名匹配、访问权限允许,不加也能多态,只是风险极高 - 在 lombok 的
@Data类里手动加@Override到toString()上,结果 lombok 自动生成的同名方法和你的冲突,编译失败 - 父类方法被删了,但子类忘了删对应
@Override方法,编译直接报错——这反而是好事,说明它在帮你发现过期代码
性能 / 兼容性影响:零。注解在编译后默认不保留(@Retention(RetentionPolicy.SOURCE)),不会进入 class 文件,也不影响 JVM 加载或反射。
什么时候不该加 @Override
只有两种合理情况:
- 你明确在定义一个新方法,比如工具方法
parseJsonSafe(),跟父类/接口毫无关系 - 你在重载(overload)而非重写(override),比如父类有
save(User u),你新增save(User u, boolean async)—— 这是重载,加@Override会编译失败
一个容易被忽略的细节:泛型类型擦除后是否一致,会影响 @Override 判定。比如父类方法是 ,子类写 Integer getValue() 是合法重写;但若写成 ,擦除后签名变成 Object getValue(),就不匹配了。







