java多态的核心是父类或接口引用指向子类对象,需同时满足继承/实现关系、子类重写非静态非私有非final方法、父类类型声明+子类构造器创建三个条件。

Java 中多态的核心落地方式,就是用父类(或接口)类型的引用变量,指向子类创建的实际对象。它不是语法炫技,而是让代码依赖“契约”而非“实现”的日常实践。
怎么写才算真正启用多态
必须同时满足三个条件:
- 存在继承或实现关系(如
class Dog extends Animal或class WechatPay implements Payment) - 子类重写了父类的非静态、非私有、非 final 的实例方法
- 声明用父类类型,创建用子类构造器:例如
Animal a = new Dog();或Payment pay = new Alipay();
运行时到底调谁的方法
编译期只检查“能不能调”——看父类里有没有这个方法声明;运行时才决定“调谁的”——JVM 查该对象所属类的虚方法表(vtable),执行实际类中重写后的版本。
-
a.sound()→ 执行Dog.sound()(前提是Dog重写了sound) -
a.name→ 访问的是Animal类里的name字段(字段不参与多态) -
a.print()→ 调用Animal.print()(静态方法绑定在编译期)
为什么不能直接用子类类型写
直接写 Dog d = new Dog(); 看似简单,但会带来硬编码问题:
- 新增
Cat类,所有用Dog类型的地方都要改 - 测试时无法轻松替换为模拟对象(如
MockCat) - 业务逻辑和具体实现耦合,比如支付写死
WechatPay,换渠道就得动业务代码
能做什么,不能做什么
父类引用像一扇带框的窗,只展示父类定义的公共能力:
- ✅ 可安全调用父类声明、且被子类重写的方法(自动走子类逻辑)
- ✅ 可传入方法参数、存入泛型集合(如
List<animal></animal>),统一处理 - ❌ 不能直接调用子类独有的方法(如
Dog.bark()),编译报错 - ❌ 不能访问子类新增字段,也不能让同名字段表现多态(应改用
getName()这类可重写的方法)
需要子类特有能力?先用 if (a instanceof Dog) 判断,再安全转型;Java 14+ 可用模式匹配简化为 if (a instanceof Dog dog) { dog.bark(); }。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











