两者都重复使用一个方法的名称,但它们从根本上是不同的。重载 = 相同的名称,不同的参数,在同一个类中,在编译时解决。重写 = 子类用相同的签名来替换父类方法,在运行时解决。
| 重载 | 重写 |
|---|
| 签名 | 必须不同(参数) | 必须相同 |
| 关系 | 同一类 | 父类 ↔ 子类 |
| 解决方式 | 编译时(静态) | 运行时(动态) |
| 目的 | 便利 / 变体 | 多态性 |
class Printer {
void print(String s) { System.out.println(s); }
void print(int n) { System.out.println(n); } // same name, diff param
void print(String s, int times) { /* ... */ }
}
编译器根据参数类型选择调用哪个 print — 不涉及继承。
class Animal { String speak() { return "..."; } }
class Dog extends Animal {
@Override
String speak() { return "Woof"; } // replaces Animal.speak()
}
Animal a = new Dog();
a.speak(); // "Woof" — runtime picks Dog's version (dynamic dispatch)
一个常见的错误是无意中重载当你本想重写时(例如签名中的拼写错误)。始终使用 @Override(Java)或 override(C#)以便编译器捕捉到它。
重写是多态性的引擎 — 运行时机制,使得"一个接口,多种实现"的概念得以运作。
了解两者的区别可以防止一个经典错误:认为你替换了行为,而实际上你只是创建了第二个永远不会被调用的方法。