方法重载是编译期行为,依据方法名和参数列表(个数、类型、顺序)区分,返回类型等无关;重写是运行期行为,要求子类方法与父类方法名、参数相同,返回类型协变、访问权限不缩小,且仅适用于非static、非final、非private方法。

Java 中方法重载(overloading)是编译期行为,靠参数列表区分;而重写(overriding)是运行期行为,发生在子类对父类方法的重新实现——二者根本不在同一维度,混用或混淆会导致编译失败或逻辑错乱。
方法重载只看参数列表,返回类型无关
重载的判定唯一依据是:方法名相同 + 参数个数、类型或顺序不同。返回类型、访问修饰符、异常声明全都不参与判断。
常见错误现象:void print(String s) 和 String print(String s) 无法构成重载,编译报错 duplicate method print(String)。
- 允许参数类型自动提升:如
int可匹配long参数的方法,但优先选精确匹配 - 可变参数(
String...)是重载的“兜底选项”,只有在无更精确匹配时才触发 - 泛型擦除后若签名重复(如
List<string></string>和List<integer></integer>),编译器会拒绝重载
重写必须满足协变规则,且不能缩小访问权限
重写发生在继承关系中,子类方法必须与父类被重写方法具有:相同方法名、相同参数列表、兼容的返回类型(支持协变返回)、不抛出新或更宽泛的检查异常。
立即学习“Java免费学习笔记(深入)”;
典型陷阱:protected void run() 在子类中被声明为 private void run(),编译直接失败——访问权限只能扩大(private → protected → public)。
-
@Override注解不是可选的,它能帮你提前发现拼写错误或签名不匹配 - 静态方法不能被重写(只能被隐藏),即使加了
@Override也会编译报错 - 构造器、
final方法、私有方法均不可重写
重载和重写同时存在时,调用目标由“编译时类型 + 实际参数”决定
这是最容易踩坑的环节:编译器先按引用类型(不是实际对象类型)确定候选重载方法集,再从中选出最匹配的一个;运行时才根据对象实际类型决定是否走重写逻辑。
示例:Animal a = new Dog(); a.eat("bone"); —— 编译器查 Animal 类里所有 eat(String) 的重载版本;若 Dog 重写了该方法,则运行时执行 Dog.eat(String)。
- 如果
Animal没有eat(String),但有eat(Object),而Dog自己定义了eat(String),那这属于重载而非重写,a.eat("bone")仍调用Animal.eat(Object) - 重载解析完全在编译期完成,和多态无关;重写才是多态的基石
真正难的不是记规则,而是当 IDE 没报错、程序却没走预期方法时,得立刻反应过来:是重载没生效?还是重写被绕过了?抑或静态绑定误用了动态语义?这时候翻源码、打日志、看字节码比背概念管用得多。







