在Java面向对象编程体系中,方法重载和重写是实现多态的两种核心方式,二者虽然都涉及方法的定义调整,但本质、使用场景和规则存在明显差异,很多开发者在初学阶段容易混淆两者的概念。

什么是方法重载
方法重载指的是在同一个类中,允许定义多个同名的方法,只要这些方法的参数列表不同即可,和方法的返回类型、访问修饰符、异常抛出都没有关系。它属于编译时多态,编译器在编译阶段就能根据调用时传入的参数确定具体执行哪个方法。
方法重载的参数列表不同包含以下几种情况:
- 参数个数不同
- 参数类型不同
- 参数顺序不同(前提是参数类型不一致)
下面是一个方法重载的示例代码:
public class OverloadDemo {
// 无参的add方法
public int add() {
return 0;
}
// 两个int参数的add方法
public int add(int a, int b) {
return a + b;
}
// 三个int参数的add方法,参数个数不同
public int add(int a, int b, int c) {
return a + b + c;
}
// 两个double参数的add方法,参数类型不同
public double add(double a, double b) {
return a + b;
}
// 先int后double参数的add方法,参数顺序不同
public double add(int a, double b) {
return a + b;
}
// 先double后int参数的add方法,参数顺序不同
public double add(double a, int b) {
return a + b;
}
}
什么是方法重写
方法重写指的是子类继承了父类的方法之后,对父类中已有的方法进行重新实现,要求子类方法的方法签名(方法名+参数列表)必须和父类完全一致。它属于运行时多态,程序运行阶段才会根据对象的实际类型确定执行父类还是子类的方法。
方法重写需要遵循以下核心规则:
- 方法名、参数列表必须和父类被重写方法完全一致
- 返回类型如果是基本类型,必须和父类一致;如果是引用类型,子类返回类型必须是父类返回类型的子类或者一致
- 子类方法的访问修饰符不能比父类被重写方法的访问修饰符更严格,比如父类是public,子类不能是protected或者private
- 子类方法抛出的异常不能比父类被重写方法抛出的异常更宽泛
- 父类的private方法、static方法、final方法不能被重写
下面是方法重写的示例代码:
// 父类
class Parent {
public void sayHello() {
System.out.println("我是父类");
}
public String getInfo() {
return "parent info";
}
protected void doSomething() {
System.out.println("父类执行操作");
}
}
// 子类
class Child extends Parent {
// 重写sayHello方法
@Override
public void sayHello() {
System.out.println("我是子类");
}
// 重写getInfo方法,返回类型是父类返回类型的子类
@Override
public String getInfo() {
return "child info";
}
// 重写doSomething方法,访问修饰符和父类一致
@Override
protected void doSomething() {
System.out.println("子类执行操作");
}
}
方法重载与重写的核心区别
我们可以从多个维度对比两者的差异,具体如下表所示:
| 对比维度 | 方法重载 | 方法重写 |
|---|---|---|
| 发生范围 | 同一个类中,或者子类继承父类后也可以重载父类的方法 | 必须发生在有继承关系的子类和父类之间 |
| 方法签名要求 | 方法名相同,参数列表必须不同 | 方法名、参数列表必须完全一致 |
| 返回类型要求 | 没有要求,可以相同也可以不同 | 基本类型必须一致,引用类型必须是父类返回类型的子类或一致 |
| 访问修饰符要求 | 没有要求 | 子类不能比父类更严格 |
| 异常抛出要求 | 没有要求 | 子类不能抛出比父类更宽泛的异常 |
| 多态类型 | 编译时多态 | 运行时多态 |
| 绑定时机 | 编译阶段确定执行的方法 | 运行阶段根据对象实际类型确定执行的方法 | >
| static/final/private方法 | 可以重载 | 不能被重写 |
常见误区说明
很多开发者会误以为返回类型不同也能构成方法重载,实际上这是错误的,仅返回类型不同而参数列表相同的方法,编译器会认为是重复定义,无法编译通过。比如下面这段代码会报错:
public class ErrorDemo {
public int test() {
return 1;
}
// 仅返回类型不同,参数列表相同,编译报错
public String test() {
return "test";
}
}
另外需要注意,@Override注解是Java提供的编译时检查注解,添加该注解后,如果方法不符合重写规则,编译器会直接报错,建议在重写方法时都添加这个注解,避免写出不符合规则的重写方法。
总结
方法重载和重写是Java多态特性的两种实现方式,重载侧重同一个类中同名方法的灵活定义,重写侧重子类对父类方法的定制化实现。实际开发中,重载常用于提供同一功能的不同参数入口,比如工具类的多个重载方法;重写常用于面向接口编程时,不同子类对接口方法的差异化实现。只要牢记两者的核心规则和差异,就能在开发中正确运用这两个特性。