@Override 是什么?
@Override 是一个 注解(Annotation),而不是一个关键字,它放在方法声明的前面,用来告诉编译器:“我,这个方法的开发者,明确地意图重写(覆盖)父类中的一个方法”。

它是一个“声明”或“意图声明”,向编译器和阅读代码的人表明这是一个重写方法。
为什么需要 @Override?(它的核心作用)
@Override 的主要作用是 编译时检查,可以帮助开发者避免一些常见的、难以发现的错误。
假设你想要重写父类的方法,但由于拼写错误,你可能并没有真正地重写它。@Override 注解会捕获这类错误。
正确使用 @Override
class Animal {
public void makeSound() {
System.out.println("Some generic animal sound");
}
}
class Dog extends Animal {
// 我们意图重写 makeSound() 方法
@Override // 编译器检查:Dog类中确实有一个makeSound()方法与父类的方法签名(方法名+参数列表)完全匹配。
public void makeSound() {
System.out.println("Woof!");
}
}
这段代码没有问题,编译通过。

错误情况下,@Override 如何拯救你
这是一个非常经典的错误场景:方法名拼写错误。
class Animal {
public void makeSound() {
System.out.println("Some generic animal sound");
}
}
class Cat extends Animal {
// 我们本意是想重写 makeSound(),但手一抖,写成了 makeSoud()
// 如果没有 @Override,编译器只会认为这是 Cat 类的一个新方法,不会报错。
// 这就导致了逻辑上的严重错误:父类的 makeSound() 方法没有被覆盖,Cat 对象调用 makeSound() 时,执行的是父类的逻辑。
@Override // 编译器在这里会报错!
public void makeSoud() { // 注意:这里拼写错误了!
System.out.println("Meow!");
}
}
会发生什么?
-
没有
@Override时:代码会成功编译,当你创建一个Cat对象并调用makeSound()时,输出的是 "Some generic animal sound",这显然不是你想要的结果,这种 bug 非常隐蔽,难以排查。 -
有
@Override时:编译器会立即报错,错误信息类似:method does not override or implement a method from a supertype(该方法没有重写或实现超类型中的方法)编译器告诉你:
Cat类中的makeSoud()方法,在它的父类Animal中找不到一个签名完全匹配的方法(父类是makeSound()),@Override注解无效,你立刻就能发现并修正这个拼写错误。
@Override 的工作原理(重写 vs 重载)
要理解 @Override 为什么有效,必须先分清 重写 和 重载 的区别。
| 特性 | 重写 | 重载 |
|---|---|---|
| 定义 | 子类提供一个与父类方法签名完全相同(方法名、参数列表)的方法,实现不同的功能。 | 在同一个类中,定义多个方法名相同但参数列表不同(参数个数、类型、顺序不同)的方法。 |
| 目的 | 实现多态,子类可以根据自己的需求实现特定行为。 | 提供多种方式调用同一个方法,通过不同的参数来区分。 |
| 返回值 | 必须与父类相同或是其子类(协变返回类型)。 | 可以不同。 |
| 异常 | 子类方法抛出的异常不能比父类更宽泛(可以是相同、更窄,或者不抛出)。 | 可以抛出不同的异常。 |
@Override 只对 重写 有效,对 重载 无效。
示例:@Override 与重载
class Vehicle {
public void start() {
System.out.println("Vehicle is starting...");
}
}
class Car extends Vehicle {
// 情况一:正确的重写
@Override
public void start() {
System.out.println("Car is starting with a key...");
}
// 情况二:这不是重写,而是重载
// @Override // 如果在这里加上 @Override,编译器会报错!
// 因为 public void start(String ignitionType) 在父类 Vehicle 中不存在一个完全匹配的方法。
public void start(String ignitionType) {
System.out.println("Car is starting with " + ignitionType + "...");
}
}
在 Car 类中,start(String ignitionType) 是一个重载方法,而不是重写,所以给它加上 @Override 注解是错误的,编译器会报错。
@Override 的使用规则(
- 不是必须的:从语法上讲,重写方法可以不加
@Override注解。强烈推荐始终使用它。 - 用于方法重写:它只能用于标记方法,表示该方法意图重写父类(或接口)的方法。
- 签名必须匹配:被
@Override标记的方法,其方法名、参数列表(参数个数和类型)必须与父类中的方法完全一致。 - 返回值类型:在 Java 5/6 中,返回值类型也必须完全一致,从 Java 7 开始,引入了协变返回类型,子类方法的返回值类型可以是父类方法返回值类型的子类,
@Override仍然有效。 - 访问修饰符:子类方法的访问修饰符不能比父类更严格,父类是
public,子类不能是protected或private。
最佳实践
- 永远使用它:养成一个好习惯,只要你是为了重写父类的方法,就在前面加上
@Override,它能成为你的“安全网”。 - 在 IDE 中使用:现代的集成开发环境(如 IntelliJ IDEA, Eclipse)非常智能,当你想要重写一个方法时,可以使用快捷键(如
Ctrl + O或Alt + Insert),IDE 会自动为你生成带有@Override注解的方法,这可以大大减少手动输入和出错的可能性。
| 特性 | 描述 |
|---|---|
| 是什么 | 一个 Java 注解,用于标记意图重写父类方法。 |
| 核心作用 | 编译时检查,防止因方法名拼写错误或参数不匹配导致的重写失败。 |
| 工作原理 | 确保被标记的方法与父类中的方法签名(方法名+参数列表)完全一致。 |
| 与重载的区别 | @Override 只对重写有效,对重载无效。 |
| 最佳实践 | 强烈推荐在所有重写方法上都使用 @Override 注解,以提高代码的健壮性和可读性。 |
掌握 @Override 是每个 Java 程序员的基本功,它能帮你写出更可靠、更专业的代码。
