Java方法重写需满足签名一致、访问权限不缩、异常声明不扩、返回类型协变四大规则,static/final/private方法不可重写,必须使用@Override注解进行编译期校验。

Java 中方法重写不是简单地“名字一样就行”,它是一套有严格约束的语法规则。写错不仅编译不通过,还可能造成逻辑隐晦、行为意外的问题。关键在于签名一致、权限不缩、异常不扩、返回兼容。
方法签名必须完全一致
这是重写的硬门槛。子类方法名、参数个数、每个参数的类型和顺序,必须与父类方法一模一样。注意:
- 参数名可以不同,不影响重写(
int a和int b是同一个参数) - 可变参数
String... args与String[] args在字节码层面擦除后等价,技术上可互为重写,但混用易引发理解混乱,建议避免 - 仅返回值类型不同 ≠ 重写,而是编译错误(除非是协变返回,见下条)
访问权限不能更严格
子类方法的可见性只能等于或高于父类方法。权限等级从高到低是:public > protected > 默认(包访问) > private。
- 父类是
public→ 子类只能是public - 父类是
protected→ 子类可用protected或public,但不能是默认或private - 父类是默认(无修饰符)→ 子类只能在同包内重写,且不能降为
private或protected - 父类是
private→ 根本不可继承,子类中同名方法只是新定义,不是重写
返回类型要满足协变规则
Java 5 起支持协变返回:子类方法返回类型可以是父类返回类型的子类(仅限引用类型)。
立即学习“Java免费学习笔记(深入)”;
- 允许:父类返回
Animal,子类返回Dog;父类返回List,子类返回ArrayList - 不允许:父类返回
Object,子类返回String(String是Object子类,✅ 可以);但父类返回Number,子类返回String(❌ 无关类型,编译失败) - 基本类型与包装类不协变:父类返回
int,子类不能返回Integer(签名已不同,直接报错)
异常声明不能扩大范围
子类方法抛出的检查型异常(checked exception)只能是父类异常的子类,或不抛出;运行时异常(RuntimeException 及其子类)不受限制。
- 父类没声明异常 → 子类只能不抛,或只抛运行时异常(如
NullPointerException) - 父类抛
IOException→ 子类可抛FileNotFoundException(它是IOException子类),但不能抛Exception或SQLException - 父类抛
IllegalArgumentException(运行时异常)→ 子类可加抛、删抛、换抛,无限制
三类方法绝对不能重写
以下情况看似像重写,实则是其他机制,务必区分清楚:
-
static方法:属于类,不是实例行为。子类同名static方法是“隐藏”(hiding),调用看引用类型,而非实际对象类型 -
final方法:被显式锁定,禁止修改。子类若声明同签名方法,编译直接报错 -
private方法:仅父类内部可见,子类根本无法继承,所谓“重写”只是定义了一个全新方法,与父类无关
务必加上 @Override 注解
这不是装饰,而是编译期校验开关。
- 拼写错误(如
getNam()写成getName())、参数类型写错、返回类型不协变——加了注解立刻报错 - 父类方法被删或改名,子类代码会立即编译失败,避免“假覆盖”残留
- 接口默认方法、抽象方法实现,也必须加
@Override,统一校验逻辑
不复杂但容易忽略


















