一、💡 一句话理解
核心结论
**重载(Overload)**是同一个类中“方法名相同、参数不同”;**重写(Override)**是子类重新实现父类已有的方法。
记忆:重载看参数,重写看继承。
二、🧭 理论:它们是什么
2.1 核心区别
| 对比项 | 重载 | 重写 |
|---|---|---|
| 发生位置 | 通常在同一个类中 | 父类与子类之间 |
| 方法名 | 相同 | 相同 |
| 参数列表 | 必须不同 | 必须相同 |
| 返回值 | 不能只靠返回值区分重载 | 相同或使用协变返回类型 |
| 访问修饰符 | 可以不同 | 可以相同或扩大,不能缩小 |
| 决定时间 | 编译时根据参数决定 | 运行时根据实际对象决定 |
| 主要作用 | 同一种功能支持不同输入 | 子类改变继承来的行为 |
2.2 重载时,返回值和修饰符可以不同吗
可以不同,但判断重载只看方法名和参数列表。参数的数量、类型或顺序必须不同,不能只修改返回值或修饰符。
public int convert(int value) {
return value;
}
private String convert(String value) {
return value;
}上面是合法重载:两个方法的返回值、访问修饰符和参数类型都不同,真正使它们构成重载的是参数类型不同。
下面不是合法重载,因为参数列表相同:
int convert(int value) {
return value;
}
// 编译错误:不能只通过返回值区分方法。
String convert(int value) {
return String.valueOf(value);
}2.3 重写时,返回值和修饰符可以不同吗
返回值必须相同,或者是父类返回类型的子类型,这叫作协变返回类型。如果返回的是基本类型或 void,则必须完全相同。
访问修饰符可以相同或扩大,但不能缩小。例如,父类是 protected,子类可以改为 public,但不能改成默认访问权限或 private。
例如,父类方法是 protected Object getValue(),子类可以重写成 public String getValue():权限从 protected 扩大为 public,返回值从 Object 变为其子类型 String。
class Parent {
protected Object getValue() {
return new Object();
}
}
class Child extends Parent {
@Override
public String getValue() {
// 权限更宽,返回值是 Object 的子类型,属于合法重写。
return "Java";
}
}其他常见修饰符
static方法不能被重写,只能被隐藏;final方法不能被重写;父类的private方法对子类不可见,因此也不属于重写。
三、⚙️ 理论:它们怎么工作
3.1 重载:编译时选方法
编译器根据参数的数量、类型和顺序,选择要调用的同名方法。
void print(int value) { }
void print(String value) { }只修改返回类型不算重载,因为调用时编译器无法据此区分方法。
3.2 重写:运行时选实现
父类引用可以指向子类对象。调用实例方法时,Java 会执行实际对象所属子类的实现,这就是多态。
注意
static方法不能被重写,只能被隐藏;重写实例方法时建议添加@Override,让编译器帮助检查。
四、🚀 实践:最小示例
4.1 完整代码
文件:Demo.java
class Animal {
void speak() {
System.out.println("动物叫");
}
}
class Dog extends Animal {
@Override
void speak() {
// 重写:参数列表与父类一致,改变子类的具体行为。
System.out.println("小狗汪汪叫");
}
void eat(String food) {
System.out.println("吃一种食物:" + food);
}
void eat(String food, int count) {
// 重载:方法名相同,但参数数量不同。
System.out.println("吃 " + count + " 份 " + food);
}
}
public class Demo {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat("骨头");
dog.eat("骨头", 2);
Animal animal = new Dog();
// 实际对象是 Dog,因此运行 Dog 重写后的 speak 方法。
animal.speak();
}
}运行:
javac Demo.java
java Demo预期输出:
吃一种食物:骨头
吃 2 份 骨头
小狗汪汪叫五、🎤 面试时怎么说
5.1 30 秒标准回答
重载是一个类中存在多个同名方法,但参数列表不同,编译器会根据实参在编译期选择方法。重写发生在继承关系中,子类使用相同的方法签名重新实现父类的实例方法,运行时会根据对象的实际类型选择实现。简单记就是:重载看参数,重写看继承和实际对象。
5.2 高频追问
- **只改返回值能重载吗?**不能,方法调用无法仅凭返回值区分。
- **重载方法的访问修饰符可以不同吗?**可以,但构成重载的依据仍然是参数列表不同。
- **重写方法的返回值可以不同吗?**可以使用父类返回类型的子类型;基本类型和
void必须相同。 - **重写方法能缩小访问权限吗?**不能,只能保持不变或扩大权限。
- **
static方法能重写吗?**不能,同名同参数的static方法属于隐藏。 - **
private方法能重写吗?**不能,因为子类不能继承父类的private方法。
六、📌 总结
- 重载:同名、参数不同,编译时确定。
- 重写:继承、签名相同,运行时确定。
- 返回值或修饰符不同不能单独构成重载。
- 重写可以使用协变返回类型,访问权限只能保持或扩大。
static和private方法不参与普通实例方法的重写。