多态的核心是父类引用指向子类对象并调用重写方法,依赖动态绑定机制;重载因在编译期绑定且方法签名不同,不属多态;静态方法、字段访问、构造器中调用重写方法等均不具多态性。

多态的核心是“父类引用 + 子类对象 + 方法重写”
多态不是语法糖,也不是设计模式噱头,它是一套运行时行为调度机制:用 Animal 类型的变量,指向 Dog 或 Cat 实例,调用 makeSound() 时自动执行各自重写后的方法。关键不在“能写”,而在“JVM 怎么选中该调哪个”——靠的是方法重写(@Override)和动态绑定。
- 没重写就不是多态:如果子类没覆写父类方法,调用的仍是父类实现,哪怕对象真是子类实例
- 必须是继承关系:接口实现也算(
List<string> list = new ArrayList();</string>),但前提是接口定义了方法,实现类提供了具体逻辑 - 编译期只认引用类型:
Animal a = new Dog();中,编译器只检查Animal是否有makeSound();运行期才查a实际是不是Dog
为什么重载(Overloading)不算真正的多态?
重载发生在编译期,靠参数类型/个数区分,方法签名不同,本质是多个独立方法。它不满足“同一个接口接受不同数据类型并表现不同行为”的题干条件——因为每个重载版本都是不同的方法入口,JVM 没有“根据实际对象类型切换逻辑”的过程。
-
display(int)和display(String)是两个方法,编译时就绑死了,跟运行时对象类型无关 - 如果你把
display(Object)和display(String)同时存在,传null会编译报错:歧义,说明它根本不看实例类型 - 真要靠参数类型做行为分发,得用 visitor 模式或反射,不是语言原生多态
容易踩的坑:转型、null、静态方法
多态只对实例方法生效,且依赖对象真实类型。一旦绕开这个链条,行为就失效。
对于一个刚进入PHP 开发大门的程序员,最需要的就是一本实用的开发参考书,而不仅仅是各种快速入门的only hello wold。在开发的时候,也要注意到许多技巧和一些“潜规则”。PHP是一门很简单的脚本语言,但是用好它,也要下功夫的。同时,由于PHP 的特性,我一再强调,最NB 的PHP 程序员都不是搞PHP 的。为什么呢?因为PHP 作为一种胶水语言,用于粘合后端 数据库和前端页面,更多需
- 向下转型(
(Dog) animal)前不校验animal instanceof Dog→ClassCastException - 调用
static方法:无论Animal a = new Dog();还是直接Dog d = new Dog();,a.doStatic()都走Animal.doStatic(),静态方法不参与多态 - 字段访问不具多态性:
animal.name取的是Animal类里的name字段,哪怕Dog自己也定义了同名字段 - 构造器里调用被重写的方法:父类构造器中调
this.method(),此时子类字段还没初始化,可能读到默认值(如 0、null)
Java 多态的边界在哪?
它只管“方法调用时该进哪个字节码”,不管类型擦除、泛型约束、异常声明这些。比如:
-
List<string></string>和List<integer></integer>在运行时都是List,泛型信息已擦除,无法靠它实现多态分支 - 子类重写方法不能抛出比父类更宽的检查异常(
IOException不行,RuntimeException可以) - 接口默认方法可以被重写,但
default不等于多态起点——它只是提供一种可选实现,真正触发多态的仍是子类是否覆盖它
真正难的不是写出来,而是意识到哪些地方“看起来像多态,其实根本没走动态分派”。比如日志框架里 logger.info(...) 看似统一接口,背后可能是 SLF4J 绑定 Logback 或 Log4j2 ——那是桥接模式+服务发现,不是语言级多态。








