一、方法重载(Method Overloading)
1. 定义
方法重载是指在同一个类中 ,多个方法名称相同,但参数列表不同 (即参数类型、数量或顺序不同)。与方法的返回值类型和访问修饰符和异常声明无关。
2. 特点
-
发生在同一个类或其子类中;
-
方法名相同;
-
参数列表必须不同(参数数量、类型或顺序),否则编译报错;
-
返回值类型可以相同也可以不同,但不能仅依靠返回值区分重载;
-
访问修饰符(如 public、private)可以相同也可以不同,但不能仅依靠访问修饰符区分重载;
-
属于编译时多态(静态绑定)。
3. 示例
java
public class MathUtil {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
}
4. 参数差异的三种常见形式
-
参数个数不同
javavoid print(); void print(String s);
-
参数类型不同
javavoid print(int i); void print(double d);
-
参数顺序不同
javavoid print(int a, String b); void print(String a, int b);
5. 编译器识别规则
Java 编译器在编译阶段根据方法的**签名(signature)**来判断重载方法是否合法,并决定调用哪个版本。
✅ 方法签名 = 方法名称 + 参数类型列表(顺序 + 个数)
-
方法签名唯一,才能构成合法的重载;
-
方法的返回类型和访问修饰符不参与方法签名的判断,因此不能通过返回值来区分重载;
-
编译器在解析方法调用时,会基于调用处提供的实参类型进行静态绑定。
-
异常声明也不参与方法重载的判断
6. JVM 的方法调用机制
JVM 层面通过方法签名生成唯一的符号引用(symbol reference)来进行方法解析,方法签名在 JVM 字节码中被称为 method descriptor:
java
add(II)I // 两个int参数,返回int
add(DDD)D // 三个double参数,返回double
二、方法重写(Method Overriding)
1. 定义
方法重写是指子类继承父类 时,对父类中的非私有 方法进行覆盖式重新实现,从而实现运行时的多态行为。
2. 特点
-
发生在父子类之间;
-
方法签名相同(方法名相同,方法参数相同);
-
返回值类型要相同或是协变类型(Java 5+);
-
访问修饰符权限不能更低;
-
子类方法不能抛出比父类更多或更广的异常;
-
发生在运行期,属于运行时多态(动态绑定)。
3. 示例
java
class Animal {
public void speak() {
System.out.println("Animal speaks");
}
}
class Dog extends Animal {
@Override
public void speak() {
System.out.println("Dog barks");
}
}
java
Animal animal = new Dog();
animal.speak(); // 输出:Dog barks
静态方法属于类本身,不参与运行时多态。子类定义相同签名的静态方法,只是隐藏了父类的方法,不构成重写。
4. 重写规则(JDK 8)
条件 | 要求 |
---|---|
类关系 | 必须是子类对父类方法进行重写 |
方法名 | 必须相同 |
参数列表 | 必须完全相同 |
返回类型 | 相同或协变(子类) |
访问修饰符 | 不能比父类方法更严格 |
抛出异常 | 不能比父类抛出更宽泛的受检异常 |
修饰符限制 | final 方法不能被重写,private 方法不能被重写 |
静态方法 | 不能被重写,只能被隐藏(称为隐藏而非重写) |
5. @Override 注解的作用
-
用于标识方法是重写父类方法;
-
编译器会检查是否真的构成了重写;
-
建议在所有重写方法上使用该注解,增强可读性和安全性。
三、方法重载与重写对比总结
对比项 | 重载(Overload) | 重写(Override) |
---|---|---|
定义关系 | 同类中方法名相同,参数不同 | 子类中重新定义父类的方法 |
参数列表 | 必须不同 | 必须相同 |
返回类型 | 可相同可不同 | 必须相同或子类型(协变) |
修饰符 | 无限制 | 子类不能更严格 |
异常限制 | 无限制 | 不能比父类抛出更广的受检异常 |
多态 | 编译期行为 | 运行时行为 |
绑定时机 | 编译时绑定(静态绑定) | 运行时绑定(动态绑定) |
注解使用 | 不使用 @Override | 建议使用 @Override |
是否继承关系 | 无需继承 | 必须继承 |
四、返回类型协变(Java 5+)
1. 定义
从 Java 5 开始 ,允许在子类中重写父类方法时,方法的返回类型可以是父类返回类型的子类,这称为协变返回类型。
2. 示例代码
java
class Parent {
public Number getValue() {
return 42;
}
}
class Child extends Parent {
@Override
public Integer getValue() {
return 24;
}
}
3. 原理说明
-
协变返回类型增强了面向对象的表达能力;
-
JVM 在运行时仍能识别正确的方法实现;
-
适用于对象返回值 ,不适用于基本类型(int、double)。