多态是Java运行时根据实际对象类型决定调用哪个方法的机制,需同时满足继承、方法重写、向上转型三个条件;仅适用于非static、非private、非final的实例方法,字段和静态方法无多态。

多态不是语法糖,也不是“写起来高级”的装饰,它是 Java 运行时根据实际对象类型决定调用哪个方法的机制——前提是满足继承 + 方法重写 + 向上转型这三个条件。
多态成立的三个必要条件
缺一不可,少一个就只是普通调用:
- 有继承关系(
class Dog extends Animal)或实现接口(class Dog implements Pet) - 子类重写了父类的非
private、非static、非final方法(@Override修饰的void speak()) - 使用父类/接口类型声明引用,但指向子类对象(
Animal a = new Dog();)
如果写成 Dog d = new Dog(); d.speak();,哪怕方法被重写,也不算多态——这是静态绑定,编译期就确定了。
多态只适用于实例方法,不适用于字段和静态方法
字段访问看的是引用类型,不是实际对象类型;静态方法绑定在编译期,跟对象实例无关。这两个是新手最容易误以为“也有多态”的地方:
立即学习“Java免费学习笔记(深入)”;
-
Animal a = new Dog(); System.out.println(a.name);→ 输出Animal类里的name值,不是Dog的 -
a.staticMethod();→ 调用的是Animal.staticMethod(),哪怕Dog里定义了同签名的static方法,也不会被选中 - 只有
a.speak();这种非静态、可重写的方法,才会在运行时查Dog对象的实际speak()实现
为什么 instanceof 和强制转型经常跟着多态一起出现
多态让接口统一,但也带来了“能力模糊”问题:你只知道它是个 Animal,但不确定它能不能飞、会不会抓老鼠。这时候需要安全地向下转型:
- 先用
if (a instanceof Bird)判断,再Bird b = (Bird) a;转型调用b.fly() - 漏掉
instanceof直接强转,遇到不匹配类型会抛ClassCastException - Java 14+ 可用模式匹配简化:
if (a instanceof Bird b) { b.fly(); },b已自动转型并作用域有效
真正难的不是理解“父类引用指向子类对象”,而是意识到:多态的价值不在写法,而在解耦——比如集合存 List,遍历时统一调 speak(),新增 Cat 类不用改已有循环逻辑。但这也意味着,所有运行时行为都依赖正确重写,漏写 @Override 或错写方法签名,多态就静默失效了。








