编译时多态和运行时多态
编译时多态和运行时多态
编译时多态(静态多态)和运行时多态(动态多态)是面向对象编程(OOP)中多态性实现的两种不同方式,分别在编译时和运行时决定方法的绑定。两者的实现方式、适用场景和特点有所不同。
1. 编译时多态(Compile-time Polymorphism)
编译时多态,也叫静态多态,是在编译阶段决定方法的调用。编译时多态主要通过**方法重载(Method Overloading)**来实现。
方法重载(Method Overloading):
方法重载是指在同一个类中定义多个方法,这些方法具有相同的方法名,但参数列表不同(参数的类型或数量不同)。Java 编译器根据方法调用时传入的参数类型和数量,在编译阶段决定调用哪个重载方法。
- 特点:
- 方法名相同,但参数不同(可以是数量、类型或顺序的变化)。
- 编译时根据传入参数类型选择匹配的方法。
- 重载方法的返回类型不影响重载的决策。
示例代码:
class Example {
void display(int a) {
System.out.println("Integer: " + a);
}
void display(double a) {
System.out.println("Double: " + a);
}
void display(String a) {
System.out.println("String: " + a);
}
}
public class Main {
public static void main(String[] args) {
Example obj = new Example();
obj.display(5); // 调用 display(int a)
obj.display(3.14); // 调用 display(double a)
obj.display("Hello"); // 调用 display(String a)
}
}
- 解释:在上面的代码中,
display()方法被重载了三次,分别处理不同类型的参数(int、double和String)。编译器会在编译时根据参数的类型来决定调用哪个版本的display()方法。
编译时多态的优势:
- 高效:编译器能够在编译阶段确定调用的方法,因此在运行时没有额外的开销。
- 类型安全:由于编译时就确定了方法的调用,避免了运行时类型错误。
2. 运行时多态(Runtime Polymorphism)
运行时多态,也叫动态多态,是在程序运行时决定方法的调用。运行时多态通常是通过**方法重写(Method Overriding)**来实现。
方法重写(Method Overriding):
方法重写是子类重新定义父类中已有的方法,并提供不同的实现。当通过父类引用调用方法时,实际执行的是子类重写后的方法。此时方法的绑定是根据对象的实际类型,而不是引用类型来决定的。方法重写是实现运行时多态的关键。
- 特点:
- 子类重写父类的方法,方法名和参数列表必须相同。
- 运行时根据对象的实际类型来决定调用哪个方法。
- 可以通过父类引用指向子类对象,表现出不同的行为。
示例代码:
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
void sound() {
System.out.println("Cat meows");
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog(); // Animal reference but Dog object
Animal myCat = new Cat(); // Animal reference but Cat object
myDog.sound(); // 输出: Dog barks
myCat.sound(); // 输出: Cat meows
}
}
- 解释:在这个例子中,
Animal是父类,Dog和Cat是子类。尽管myDog和myCat都是Animal类型的引用,但它们分别指向Dog和Cat对象。在调用sound()方法时,实际执行的是子类重写后的方法。
运行时多态的优势:
- 灵活性和可扩展性:通过父类类型的引用可以调用不同子类的实现,使得代码具有更高的灵活性和可扩展性。
- 实现多态性:运行时多态允许在程序运行时决定对象的行为,这使得程序能够根据不同的对象表现出不同的行为。
总结:编译时多态与运行时多态的区别
| 特点 | 编译时多态(静态多态) | 运行时多态(动态多态) |
|---|---|---|
| 实现方式 | 方法重载(Method Overloading) | 方法重写(Method Overriding) |
| 方法绑定时机 | 编译时 | 运行时 |
| 决策依据 | 方法名相同,参数列表不同 | 方法名和参数列表相同,依据对象的实际类型 |
| 多态类型 | 静态多态,方法的调用在编译时就确定 | 动态多态,方法的调用在运行时决定 |
| 类型 | 方法签名不同(参数不同) | 子类重写父类方法 |
| 调用机制 | 根据方法参数类型选择正确的方法 | 根据实际对象类型选择调用的重写方法 |
| 优点 | 性能较高,编译时就能确定调用方法 | 提高了灵活性和可扩展性,支持多态性 |
相关笔记
多态的载体是方法重写,完整规则见 重写与重载;多态在本篇讲"绑定时机",继承与多态 讲"整体图景",三篇互补。
💬 评论