重写方法必须方法名、参数列表完全一致,返回类型协变,访问修饰符不能更严格,且仅适用于非static、非final、非private的实例方法;需用@Override校验。

重写方法必须有相同的方法签名
Java要求重写(override)的方法名、参数列表(类型、数量、顺序)必须和父类中被重写的方法完全一致。返回类型可以是父类返回类型的协变子类型(比如父类返回 Object,子类可返回 String),但不能是无关类型或更宽泛的类型。
常见错误:参数类型写成 int 而父类是 Integer,或误加默认参数(Java不支持默认参数)、改变参数顺序——这些都会导致编译器认为是重载(overload),而非重写。
- 方法名必须相同
- 参数列表必须逐个匹配(包括基本类型与包装类的严格区分)
- 返回类型满足协变规则,否则编译报错:
error: return type is not compatible with ...
访问修饰符不能比父类更严格
子类重写方法的访问权限只能等于或大于父类方法的访问级别。比如父类是 protected,子类可以是 protected 或 public,但不能是 private 或包私有(即不写修饰符)。
否则编译失败,错误信息类似:error: method does not override or implement a method from a supertype(注意:这未必是签名问题,也可能是访问权限太小导致编译器“看不见”可重写的方法)。
立即学习“Java免费学习笔记(深入)”;
-
public→ 只能重写为public -
protected→ 可重写为protected或public - 包私有(无修饰符)→ 可重写为包私有、
protected或public(前提是子类与父类在同一个包) -
private方法不能被重写(它对子类不可见)
@Override 注解不是可选的“装饰”,而是编译期校验工具
加上 @Override 后,编译器会强制检查:该方法是否真的在父类或接口中存在可被重写的方法。一旦签名写错、父类方法被删、或父类方法是 final / private,就会立刻报错。
没加 @Override 时,即使你本意是重写,也可能因拼写错误变成新增方法,运行时多态失效,而编译器沉默放行——这是线上逻辑 bug 的高发源头。
- 始终显式添加
@Override,哪怕 IDE 没提示 - 如果加了
@Override却报错,不要删注解,应检查父类方法是否存在、是否可访问、是否被final修饰 - 接口默认方法(
default)也可被重写,同样需要@Override
static、final 和 private 方法不能被重写
重写只发生在实例方法(非静态、非私有、非 final)的运行时动态绑定过程中。以下三类方法在编译期就绑定到声明类型,与多态无关:
-
static方法:可“隐藏”(hide),但不是重写;调用取决于引用类型,而非实际对象类型 -
final方法:编译器禁止子类覆盖,强行写会报错:error: cannot override final method -
private方法:对子类不可见,子类中同名方法属于全新定义,与父类无任何重写关系
容易忽略的是:父类中 private void init() 和子类中 public void init() 看似一样,实则毫无关系。哪怕子类对象被向上转型为父类引用,调用的仍是父类自己的 private init()(如果父类有调用逻辑),而子类版本根本不会参与分派。







