Java中的方法重载和覆盖是实现多态的两种核心方式,但两者的生效时机、实现规则和应用场景存在明显差异,很多开发者在初学阶段容易混淆这两个概念,下面我们从基础定义到实际代码逐一解析。

方法重载:编译期多态的实现
方法重载指的是在同一个类中,定义多个方法名相同但参数列表不同的方法,编译器会在编译阶段根据传入的参数类型和数量确定具体调用哪个方法,因此属于编译期多态。
重载的核心规则
- 方法名必须完全相同
- 参数列表必须不同,包括参数类型、参数数量、参数顺序(仅参数顺序不同也需要参数类型有差异,否则无意义)
- 返回值类型、访问修饰符、抛出的异常列表可以不同,这些不属于重载的判断条件
重载代码示例
下面是一个简单的重载示例,同一个Calculator类中定义了多个add方法:
public class Calculator {
// 两个整数相加
public int add(int a, int b) {
return a + b;
}
// 三个整数相加,参数数量不同
public int add(int a, int b, int c) {
return a + b + c;
}
// 两个浮点数相加,参数类型不同
public double add(double a, double b) {
return a + b;
}
// 先传整数再传浮点数,参数顺序不同(和先浮点后整数的方法区分)
public double add(int a, double b) {
return a + b;
}
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(1, 2)); // 调用两个int参数的方法,输出3
System.out.println(calc.add(1.5, 2.5)); // 调用两个double参数的方法,输出4.0
}
}方法覆盖:运行时多态的核心
方法覆盖也叫方法重写,指的是子类继承父类后,定义一个和父类方法签名完全相同的方法,程序运行时会根据对象的实际类型调用对应的方法,属于运行时多态,是面向对象多态特性的核心体现。
覆盖的核心规则
- 子类方法的方法名、参数列表、返回值类型必须和父类方法完全一致(返回值类型如果是父类方法返回类型的子类,也符合协变返回类型规则)
- 子类方法的访问修饰符不能比父类方法的更严格,比如父类方法是
public,子类不能是protected或private - 子类方法抛出的异常不能比父类方法抛出的异常更宽泛,只能是父类方法抛出异常的子类或者不选抛出
- 父类的
private方法、static方法、final方法不能被覆盖
覆盖代码示例
下面通过父类和子类的示例展示方法覆盖的效果:
// 父类
class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
// 子类Dog继承Animal
class Dog extends Animal {
// 覆盖父类的makeSound方法
@Override
public void makeSound() {
System.out.println("狗汪汪叫");
}
}
// 子类Cat继承Animal
class Cat extends Animal {
// 覆盖父类的makeSound方法
@Override
public void makeSound() {
System.out.println("猫喵喵叫");
}
}
public class TestOverride {
public static void main(String[] args) {
Animal animal1 = new Dog(); // 父类引用指向子类对象
Animal animal2 = new Cat(); // 父类引用指向子类对象
animal1.makeSound(); // 运行时根据实际类型调用Dog的方法,输出狗汪汪叫
animal2.makeSound(); // 运行时根据实际类型调用Cat的方法,输出猫喵喵叫
}
}重载与覆盖的核心差异对比
为了更清晰地区分两者,我们可以通过表格对比关键特性:
| 对比维度 | 方法重载 | 方法覆盖 |
|---|---|---|
| 发生范围 | 同一个类内部 | 子类与父类之间 |
| 判断核心 | 方法名相同,参数列表不同 | 方法签名完全一致 |
| 多态类型 | 编译期多态(静态绑定) | 运行时多态(动态绑定) |
| 返回值要求 | 无要求 | 必须一致或是协变类型 |
| 访问修饰符要求 | 无要求 | 子类不能比父类更严格 |
多态行为的实际意义
方法重载让同一个类可以处理不同类型的输入,减少方法命名的复杂度,比如System.out.println就重载了多种参数类型的方法,可以打印不同类型的数据。方法覆盖则让子类可以定制父类的行为,配合父类引用指向子类对象的用法,可以在不修改原有代码的基础上扩展功能,符合开闭原则,是很多设计模式的基础实现逻辑。