社交媒体

多态

多态

钩子:一行代码,一个谜

Person p = new Student();   // 左边是 Person,右边 new 的是 Student
p.introduce();

问题来了:p 的类型是 Person,但它在内存里指向的是一个 Student 对象。p.introduce() 到底执行哪个版本?

如果你的 Student 重写 introduce()(第 18 篇的代码),输出是——学生版台词。

左边声明的是父类,右边造的是子类,执行的却是子类的方法。这就是多态(Polymorphism):同一个方法调用,跟着对象的"真实身份"走。

核心:编译看左边,运行看右边

拆成两半理解:

  1. 编译器看左边:p 的类型是 Person,所以你只能调 Person 里声明过的方法。调 p.study()(Student 独有的)?编译报错——编译器只认"户口";
  2. 运行时看右边:真正执行时,JVM 找的是 p 指向的实际对象(Student),重写过的方法跑子类版本——行为跟"血统"走。

一句话记住:能调什么,看左边;怎么执行,看右边。

19-多态执行对比图.png

多态有什么用?一个方法管一群对象

不 用多态,想给所有对象做自我介绍,得写一堆 if-else:

if (x instanceof Student) { ((Student) x).introduce(); }
else if (x instanceof Employee) { ((Employee) x).introduce(); }

用多态,一个方法收下全家:

static void hello(Person p) {    // 参数是父类:Person 及其子类都能传
    p.introduce();               // 自动执行真实身份的版本
}

hello(new Student());    // 学生版台词
hello(new Employee());   // 员工版台词

新增一个 Teacher 类,hello() 一行都不用改——它天然支持。这就是多态的威力:代码对"新的类型"自动开放。你以后天天用的 System.out.println(x),内部就是靠多态对万物生效的。

安检门:instanceof 与类型转换

从父类"下放"回子类,需要强转,且要先安检:

if (p instanceof Student) {
    Student s = (Student) p;    // 安检通过才能转
    s.study();                  // 现在能调 Student 独有方法了
}

不做安检直接转,遇到"身份不符"就抛 ClassCastException——它和第 12 篇的数组越界并称新手两大运行时异常。Java 21 提供了简写 if (p instanceof Student s),安检+赋值一行搞定,推荐。


本文示例代码均已本地实测通过,可直接运行。
对应文件:PolyDemo.java


橙码酱,分享更有用的技术知识,助你成为更优秀的开发者。