多态(Polymorphism)
多态是面向对象编程(OOP)中的核心概念之一,它指的是 同一接口,多个实现方式。在 Java 中,多态主要有 两种形式:
- 静态多态(Static Polymorphism)(编译时多态)
- 动态多态(Dynamic Polymorphism)(运行时多态)
1️⃣ 静态多态(Static Polymorphism)
静态多态 也叫 编译时多态,主要通过方法重载(Method Overloading) 实现。
🔹 方法重载(Method Overloading)
方法重载 指的是在 同一个类 中,方法名称相同,但参数列表(参数类型、参数个数或顺序)不同,最终由编译器在 编译期 确定调用哪个方法。
✅ 示例
class MathUtil {
// 计算两个整数相加
public int add(int a, int b) {
return a + b;
}
// 计算三个整数相加
public int add(int a, int b, int c) {
return a + b + c;
}
// 计算两个浮点数相加
public double add(double a, double b) {
return a + b;
}
}
public class StaticPolymorphismDemo {
public static void main(String[] args) {
MathUtil mathUtil = new MathUtil();
System.out.println(mathUtil.add(10, 20)); // 调用 add(int, int)
System.out.println(mathUtil.add(10, 20, 30)); // 调用 add(int, int, int)
System.out.println(mathUtil.add(5.5, 2.2)); // 调用 add(double, double)
}
}
🔍 解析
- Java 在编译时 通过参数类型和数量来决定调用哪个方法,因此称为 静态多态。
- 优点:方法重载可以提高代码的可读性,并适用于不同的数据类型。
2️⃣ 动态多态(Dynamic Polymorphism)
动态多态 也叫 运行时多态,主要通过 方法重写(Method Overriding) 和 父类引用指向子类对象 来实现。
🔹 方法重写(Method Overriding)
方法重写 指的是 子类 对 父类中继承的方法 进行重新实现,并保持方法签名(方法名、参数类型、参数个数)不变。
✅ 示例
// 父类
class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
// 子类 1:Dog
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("狗叫:汪汪");
}
}
// 子类 2:Cat
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("猫叫:喵喵");
}
}
public class DynamicPolymorphismDemo {
public static void main(String[] args) {
// 父类引用指向子类对象(向上转型)
Animal myAnimal1 = new Dog();
Animal myAnimal2 = new Cat();
// 调用方法,实际执行的是子类的实现(方法重写)
myAnimal1.makeSound(); // 输出:狗叫:汪汪
myAnimal2.makeSound(); // 输出:猫叫:喵喵
}
}
🔍 解析
Animal myAnimal1 = new Dog();
myAnimal1
是 Animal 类型的引用,但指向Dog
对象。- 当调用
myAnimal1.makeSound()
时,Java 在运行时 发现Dog
重写了makeSound()
,所以调用Dog
的方法,而不是Animal
的方法。
- 动态绑定
- Java 在运行时 确定调用哪个方法(方法绑定在运行时完成),这就是 动态多态。
🌟 关键特性
- 必须要有继承关系(子类继承父类)
- 必须要有方法重写(子类实现父类的方法)
- 必须通过父类引用指向子类对象,这样才能在运行时体现多态性
🎯 静态多态 vs 动态多态
对比项 | 静态多态(方法重载) | 动态多态(方法重写) |
---|---|---|
发生阶段 | 编译时(Compile-time) | 运行时(Runtime) |
方法定义 | 同一类中的方法,方法名相同但参数不同 | 子类重写父类方法,方法签名相同 |
方法调用确定 | 编译时由编译器决定调用哪个方法 | 运行时由 JVM 动态绑定 |
可读性 | 代码可读性高,可处理不同输入 | 适用于通用接口,提升可扩展性 |
关键特性 | 方法签名不同,返回值可以相同 | 必须有继承关系,必须使用 @Override |
示例 | add(int, int) vs add(double, double) | makeSound() 在 Dog 和 Cat 中被重写 |
💡 结论
- 静态多态(方法重载) 在编译时确定 方法调用,主要是 方法签名不同 。
- 动态多态(方法重写) 在运行时决定 方法调用,适用于 父类引用指向子类对象 的场景。
- 两者的区别在于方法的绑定时间:
- 静态多态 在 编译阶段 绑定(编译时已知调用哪个方法)。
- 动态多态 在 运行阶段 绑定(取决于实际对象类型)。
在实际开发中:
- 静态多态适用于提供多种方式处理不同的输入类型(如
println()
)。 - 动态多态适用于编写通用代码,支持更好的扩展性(如 Java 的
List<Animal>
存储Dog
和Cat
)。
这样就清楚 静态多态 vs 动态多态 了!🎯 🚀