Java 方法重写与重载
方法重写(Override)和方法重载(Overload)是 Java 中两个重要的概念,它们都涉及方法名相同但实现不同。理解它们的区别和使用场景是掌握面向对象编程的关键。本章将详细介绍方法重写与重载。
方法重写(Override)
什么是方法重写
方法重写(Override)是子类重新定义父类的方法,提供自己的实现。
// 父类
public class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
// 子类重写父类方法
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("汪汪汪");
}
}
重写的规则
- 方法签名相同:方法名、参数列表必须完全相同
- 返回类型兼容:返回类型相同或是父类返回类型的子类
- 访问修饰符不能更严格:可以更宽松,不能更严格
- 不能重写 private 方法:private 方法不能被重写
- 不能重写 final 方法:final 方法不能被重写
- 不能重写 static 方法:static 方法不能被重写(可以隐藏)
public class Animal {
public void method1() { }
protected void method2() { }
private void method3() { }
public final void method4() { }
public static void method5() { }
}
public class Dog extends Animal {
@Override
public void method1() { } // ✅ 可以重写
@Override
public void method2() { } // ✅ 可以重写(访问修饰符更宽松)
// @Override
// private void method3() { } // ❌ 不能重写 private 方法
// @Override
// public void method4() { } // ❌ 不能重写 final 方法
// @Override
// public static void method5() { } // ❌ 不能重写 static 方法
}
@Override 注解
使用 @Override 注解标识重写的方法:
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("汪汪汪");
}
}
好处:
- 编译器检查重写是否正确
- 代码更清晰
- 如果父类方法签名改变,会提示错误
方法重载(Overload)
什么是方法重载
方法重载(Overload)是同一个类中有多个同名方法,但参数列表不同。
public class Calculator {
// 重载:两个 int 参数
public int add(int a, int b) {
return a + b;
}
// 重载:三个 int 参数
public int add(int a, int b, int c) {
return a + b + c;
}
// 重载:double 参数
public double add(double a, double b) {
return a + b;
}
}
重载的规则
- 方法名相同
- 参数列表不同:参数类型、个数、顺序不同
- 返回类型可以不同:但不能仅靠返回类型区分
- 访问修饰符可以不同
public class Example {
// ✅ 参数个数不同
public void method(int a) { }
public void method(int a, int b) { }
// ✅ 参数类型不同
public void method(int a) { }
public void method(double a) { }
// ✅ 参数顺序不同
public void method(int a, String b) { }
public void method(String a, int b) { }
// ❌ 仅返回类型不同,不能重载
// public int method() { }
// public String method() { } // 编译错误
}
重写 vs 重载对比
对比表
| 特性 | 重写(Override) | 重载(Overload) |
|---|---|---|
| 方法名 | 相同 | 相同 |
| 参数列表 | 必须相同 | 必须不同 |
| 返回类型 | 相同或子类 | 可以不同 |
| 访问修饰符 | 不能更严 格 | 可以不同 |
| 发生位置 | 继承关系中 | 同一类中 |
| 调用时机 | 运行时决定 | 编译时决定 |
| 目的 | 提供不同实现 | 提供不同参数 |
代码示例
// 父类
public class Animal {
public void eat() {
System.out.println("动物吃东西");
}
public void eat(String food) { // 重载
System.out.println("动物吃" + food);
}
}
// 子类
public class Dog extends Animal {
@Override
public void eat() { // 重写
System.out.println("狗吃骨头");
}
@Override
public void eat(String food) { // 重写
System.out.println("狗吃" + food);
}
public void eat(String food, int amount) { // 重载(子类新方法)
System.out.println("狗吃" + amount + "份" + food);
}
}