Java 中重载(Overloading)与重写(Overriding)的区别
重载(Overloading) 和 重写(Overriding) 是 Java 中常见的多态性实现方式,但它们有着明显的区别,主要体现在方法签名、继承关系、编译时和运行时行为等方面。
🌟 1. 方法重载(Overloading)
定义:
- 同一个类中 方法名相同,但 参数类型、数量或顺序不同。
- 与 返回值类型无关,仅参数列表不同即可构成重载。
特点:
- 编译时多态性(静态绑定)。
- 不涉及继承关系。
- 主要用于增强方法的灵活性,提高代码可读性。
示例:
public class Calculator {
// 重载方法1: 接收两个整数
public int add(int a, int b) {
return a + b;
}
// 重载方法2: 接收三个整数
public int add(int a, int b, int c) {
return a + b + c;
}
// 重载方法3: 接收两个浮点数
public double add(double a, double b) {
return a + b;
}
}
调用示例:
Calculator calc = new Calculator();
System.out.println(calc.add(1, 2)); // 调用第一个重载方法
System.out.println(calc.add(1, 2, 3)); // 调用第二个重载方法
System.out.println(calc.add(1.5, 2.5)); // 调用第三个重载方法
🌟 2. 方法重写(Overriding)
定义:
- 子类 对 父类 中的 非私有方法 进行重新定义(方法签名、返回值、参数列表都必须相同)。
- 主要用于在继承关系中实现多态性。
特点:
- 运行时多态性(动态绑定)。
- 必须存在 继承关系(即父类与子类)。
@Override
注解可选但推荐使用,方便编译器检查。
示例:
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Dog barks");
}
}
调用示例:
Animal myDog = new Dog();
myDog.makeSound(); // 输出: Dog barks (运行时多态性)
🔍 重载 vs. 重写 - 详细对比
对比项 | 重载(Overloading) | 重写(Overriding) |
---|---|---|
发生位置 | 同一类中 | 子类与父类之间 |
方法签名 | 必须不同(参数列表不同) | 必须相同(方法名、参数类型、顺序相同) |
返回值类型 | 可以不同 | 必须相同 |
访问权限 | 不受影响 | 子类权限 ≥ 父类权限 |
注解使用 | 无需 @Override | 推荐使用 @Override |
多态类型 | 编译时多态性(静态绑定) | 运行时多态性(动态绑定) |
应用场景 | 方法的不同参数版本,如 println 方法 | 父类方法行为不满足需求时,子类重新定义 |
🚀 项目中常用的场景
✅ 重载的使用场景:
- 构造方法重载:
- 在 Spring 项目中,常用来创建对象的不同版本(如无参构造、有参构造)。
- 服务方法重载:
- 如
save()
方法,可能有接收不同类型参数的多个版本。
- 如
- 工具类方法重载:
- 如 Apache Commons 的
StringUtils
中的substring
方法。
- 如 Apache Commons 的
✅ 重写的使用场景:
- Controller 层重写
toString()
方法:- 便于日志输出对象信息。
- Spring MVC 中重写
HandlerInterceptor
的方法:- 如
preHandle()
用于权限检查。
- 如
- Spring Boot 项目中重写
@Service
方法:- 用于处理特定业务逻辑,如重写
UserService
中的getUserById()
方法。
- 用于处理特定业务逻辑,如重写
❓ 常见面试问题:
-
重载能否通过返回类型区分?
- 不能。 仅通过返回类型不同无法构成重载,必须有不同的参数列表。
-
重写时能否改变返回类型?
- 可以(但有限制)。 重写时可以使用父类返回类型的子类型(协变返回类型)。
-
private
方法能被重写吗?- 不能。
private
方法对子类不可见。
- 不能。
总结:
- 重载 主要用于提高代码的灵活性。
- 重写 则是面向对象编程中实现多态性的核心手段。
- 在项目中,两者常结合使用,适应不同场景需求。