重写是子类覆盖父类方法,体现运行时多态;重载是同一类中同名不同参的方法,属编译时多态。二者发生位置、绑定时机、JVM处理机制截然不同,@Override仅适用于重写。

重写(Override)是子类改父类方法,重载(Overload)是同一个类里多个同名但参数不同的方法
重写的本质是运行时多态:调用哪个版本,取决于对象实际类型;重载是编译时决定的,只看变量声明类型和传入参数的静态类型。很多人混淆,是因为都用了相同方法名,但发生位置、触发时机、JVM处理方式完全不同。
@Override 注解只对重写有效,加在重载方法上会编译报错
这是最直接的区分信号。Java 要求重写必须加 @Override(除非父类方法是 private 或 final),而重载方法加了它会提示 Method does not override method from its superclass。
- 重写:必须有继承关系,方法签名(名称 + 参数类型)完全一致,返回类型协变,访问权限不能更严格
- 重载:发生在同一个类中,参数列表不同(类型、个数、顺序任一不同),返回类型和访问修饰符可任意
- 构造方法只能重载,不能重写(没有继承构造方法这回事)
重载解析在编译期完成,重写绑定在运行期发生
这意味着重载选哪个方法,javac 就定死了;而重写调用谁,得等 new 出来的对象实际是哪个子类实例才能确定。这也是为什么 static 方法可以重载但不能真正重写——它不参与动态分派。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 重载示例:
print(String)和print(Object)在同一类里,传"abc"会选前者;但传new Object()就选后者 - 重写示例:父类
Animal.speak()输出 "sound",子类Dog.speak()输出 "woof",用Animal a = new Dog(); a.speak();打印的是 "woof" - 如果把
speak()声明为static,那无论a实际是什么类型,都只会调父类版本
容易被忽略的坑:重载可能意外遮蔽重写,尤其涉及自动装箱和 varargs
比如父类有 void handle(int x),子类加了个 void handle(Integer x),看起来像重载,但其实破坏了重写契约——因为 Integer 参数不会触发对父类 int 版本的重写,反而让子类失去多态行为。
- 基本类型和包装类混用重载,极易导致调用路径出人意料
- 带
...的重载方法优先级最低,但容易和其它重载产生歧义,编译器可能报reference to xxx is ambiguous - 泛型擦除后,
list(List和) list(List无法构成重载(擦除后都是) list(List)),会编译失败
重写看对象实类型,重载看引用声明类型和参数字面量;一个靠 JVM 运行时查虚方法表,一个靠 javac 编译时查符号表——底层机制差得远,别被名字带偏。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










