前言面向对象三大核心特性封装、继承、多态。其中多态是最难理解、同时也是实际开发使用最频繁的特性。很多初学者分不清父类引用指向子类对象时成员变量、成员方法到底调用哪一个本文结合两节知识点从零拆解多态核心概念再梳理多态访问成员的完整规则搭配代码示例一次性吃透。一、什么是多态1. 多态的字面含义多态即多种形态。同一个行为不同对象执行会表现出不一样的效果。 举生活例子同样是 “叫” 这个动作猫叫是喵喵狗叫是汪汪同样是 “跑”汽车和自行车的行驶方式完全不同这就是现实里的多态。2. Java 中多态的核心定义父类引用指向子类对象同一个父类引用调用重写方法时会执行子类重写后的逻辑这种编译和运行表现不一致的形态就是 Java 多态。 标准写法父类 引用名 new 子类();3. 多态存在的三个必要条件缺一不可必须有继承 / 实现关系子类继承父类或者类实现接口必须方法重写override子类重写父类同名同参数的方法否则无法体现不同行为父类引用指向子类对象Father f new Son();是多态的标准载体。4. 基础代码示例演示多态// 父类动物 class Animal { public void shout() { System.out.println(动物发出叫声); } } // 子类1猫重写shout方法 class Cat extends Animal { Override public void shout() { System.out.println(猫咪喵喵喵); } } // 子类2狗重写shout方法 class Dog extends Animal { Override public void shout() { System.out.println(小狗汪汪汪); } } public class Test { public static void main(String[] args) { // 多态写法父类引用指向子类 Animal a1 new Cat(); Animal a2 new Dog(); // 同一个shout方法不同对象表现不同形态 a1.shout(); // 输出猫咪喵喵喵 a2.shout(); // 输出小狗汪汪汪 } }运行结果可以直观看到同样是Animal类型的引用调用同一个shout()方法实际执行的是子类重写后的代码这就是多态最直观的体现。5. 多态的优缺点优点代码解耦扩展性强新增子类无需修改原有调用代码直接新增类即可方法形参统一方法接收父类类型所有子类对象都能传入不用重载多个方法代码简洁便于维护。缺点多态形式下父类引用无法直接调用子类独有的方法需要向下转型才能访问。二、多态调用成员的特点变量、方法区分对待很多人踩坑的核心点多态中成员变量、成员方法的访问规则完全不同分开记忆。 核心口诀变量看左边编译看父类方法看右边运行看子类。1. 成员变量访问规则编译运行都看左边引用类型父类编译阶段只识别父类中定义的成员变量运行阶段打印的依旧是父类的变量值和右边 new 的子类无关 简单说多态访问变量永远调用父类的变量。代码验证class Animal { String name 动物; } class Cat extends Animal { String name 猫咪; } public class TestVar { public static void main(String[] args) { Animal a new Cat(); // 多态访问成员变量取父类的值 System.out.println(a.name); // 输出动物 } }2. 普通成员方法访问规则编译看左边运行看右边编译阶段检查父类是否存在该方法不存在直接编译报错运行阶段执行子类重写后的方法 也就是我们前面演示多态的核心逻辑方法遵循重写机制优先执行子类实现。3. 静态方法访问规则编译运行都看左边父类静态方法属于类不存在重写子类同名静态方法只是隐藏父类方法多态调用静态方法时完全看引用的父类类型。class Animal { public static void run() { System.out.println(动物奔跑); } } class Cat extends Animal { public static void run() { System.out.println(猫咪奔跑); } } public class TestStatic { public static void main(String[] args) { Animal a new Cat(); a.run(); // 输出动物奔跑执行父类静态方法 } }4. 总结多态成员访问对照表成员类型编译阶段看哪边运行阶段执行哪边核心结论成员变量左边父类左边父类变量只认父类普通成员方法左边父类右边子类方法执行子类重写静态 static 方法左边父类左边父类静态属于类不看多态三、拓展多态向下转型解决无法调用子类独有方法问题前面提到多态的缺点父类引用不能直接调用子类独有的方法此时需要强制向下转型。class Animal { public void shout() {} } class Cat extends Animal { Override public void shout() { System.out.println(喵喵); } // 子类独有方法 public void catchMouse() { System.out.println(猫抓老鼠); } } public class TestCast { public static void main(String[] args) { Animal a new Cat(); a.shout(); // 正常调用重写方法 // a.catchMouse(); 编译报错父类没有该方法 // 向下转型转为子类类型 Cat c (Cat) a; c.catchMouse(); // 输出猫抓老鼠 } }注意转型时类型不匹配会抛出ClassCastException类型转换异常实际开发可以搭配instanceof关键字做类型判断。四、实战场景多态的真实开发用途开发中最常用场景工具方法接收父类参数兼容所有子类。 比如统一让所有动物发声public class TestDemo { // 形参是父类Animal所有子类Cat、Dog都能传入 public static void makeSound(Animal animal) { animal.shout(); } public static void main(String[] args) { makeSound(new Cat()); makeSound(new Dog()); } }如果不使用多态需要写makeSound(Cat)、makeSound(Dog)多个重载方法代码冗余新增动物还要新增方法扩展性极差。五、全文总结多态核心父类引用指向子类对象同一个方法呈现多种执行形态多态三大前提继承、方法重写、父类引用接收子类实例成员访问核心口诀变量、静态看父类普通方法运行看子类多态优势高扩展、低耦合统一参数接收局限是无法直接调用子类独有方法需向下转型。