多态通过父类引用调用子类重写方法避免重复分支逻辑,提升扩展性。如Shape抽象类定义area(),Circle和Rectangle各自实现,printArea(Shape s)统一处理,新增子类无需修改原有代码。

多态让同一段逻辑适配不同子类
Java 中多态性本身不直接“减少代码行数”,而是通过 父类引用指向子类对象,把重复的调用逻辑抽到统一位置,避免为每个子类写一套几乎相同的流程代码。关键在于:行为差异封装在子类的重写方法里,主流程只面向接口或父类编码。
用 Shape 举例:避免 if-else 判断类型再调用
常见冗余写法是根据对象实际类型用 if (obj instanceof Circle) 或 switch 分支调用不同方法。这种代码随子类增多而膨胀,且每次新增子类都要改原有判断逻辑。
正确做法是定义统一方法签名,在子类中各自实现:
abstract class Shape {
abstract double area();
}
class Circle extends Shape {
final double radius;
Circle(double r) { this.radius = r; }
@Override double area() { return Math.PI radius radius; }
}
class Rectangle extends Shape {
final double width, height;
Rectangle(double w, double h) { this.width = w; this.height = h; }
@Override double area() { return width * height; }
}
// 调用方无需知道具体类型
void printArea(Shape s) {
System.out.println("Area: " + s.area()); // 多态分发,自动调用对应子类实现
}
ArrayList 集合统一处理多个子类实例
当需要批量操作不同子类型的对象时,若不用多态,就得维护多个同构集合(List、List),并为每个写一遍循环逻辑。多态允许用一个泛型集合容纳所有子类,并复用同一段遍历+调用代码。
立即学习“Java免费学习笔记(深入)”;
- 必须声明为
ArrayList(或List),不能用ArrayList—— 后者丢失类型契约,编译期无法保证有area()方法 - 运行时实际调用哪个
area(),由对象真实类型决定,JVM 通过虚方法表动态绑定 - 如果子类忘记重写
area(),抽象类已强制要求实现,编译报错,不会漏逻辑
容易被忽略的边界:重载 ≠ 多态,字段访问不具多态性
新手常误以为“只要写了多个同名方法就是多态”,其实 Java 中只有 重写(override) 才触发运行时多态;重载(overload) 是编译期静态绑定,和多态无关。
另一个典型陷阱是访问字段:
class Animal { String name = "Animal"; }
class Dog extends Animal { String name = "Dog"; }
Animal a = new Dog();
System.out.println(a.name); // 输出 "Animal",不是 "Dog"
字段访问看的是引用类型(Animal),不是实际类型(Dog)。多态只适用于 非 private / static / final 的实例方法调用。
真正节省冗余的地方,从来不在语法糖上,而在你不再需要为每种新类型去翻旧代码、加分支、改 if 条件——那才是多态落地后最安静的收益。










