目录前言一、认识多态二、多态中调用成员的特点1、调用成员变量编译看左边运行也看左边。2、调用成员方法编译看左边运行看右边。3、邪修理解方式前言面向对象的三大特征封装、继承和多态实际上封装、继承和多态是一个层层递进、密不可分的有机整体。今天我们来学习面向对象特征中的多态。“万事有为应有尽此身无我自无穷。”一、认识多态多态顾名思义就是同一种行为在不同对象中的不同实现形式。生活中的多态比如“按下F1键”这一行为如果当前在桌面按下 F1 会弹出 Windows 帮助如果当前在游戏里按下 F1 可能是释放技能。同一种操作作用于不同对象结果完全不同。Java中的多态建立在继承的基础上。指同一个父类引用指向不同的子类对象时调用同一个方法会执行不同的子类逻辑。场景应用Person类public class Person { private String name; private int age; public Person() { } public Person(int age, String name) { this.age age; this.name name; } public String getName() { return name; } public void setName(String name) { this.name name; } public int getAge() { return age; } public void setAge(int age) { this.age age; } public void show(){ System.out.println(name , age); } }学生、老师、管理员类public class Student extends Person{ Override public void show(){ System.out.println(学生的信息为 getName() , getAge()); } }public class Teacher extends Person{ Override public void show(){ System.out.println(老师的信息为 getName() , getAge()); } }public class Administrator extends Person{ Override public void show(){ System.out.println(管理员的信息为 getName() , getAge()); } }测试类public class Test { public static void main(String[] args) { Student s new Student(); Teacher t new Teacher(); Administrator admin new Administrator(); s.setName(张三); s.setAge(20); t.setName(李四); t.setAge(30); admin.setName(王五); admin.setAge(35); registor(s); registor(t); registor(admin); } public static void registor(Person p ){ p.show(); } }运行结果多态的前提有继承/实现关系有父类引用指向子类对象有方法的重写二、多态中调用成员的特点成员变量调用编译看左边运行也看左边。成员方法调用编译看左边运行看右边。1、调用成员变量编译看左边运行也看左边。场景演示public class Test { public static void main(String[] args) { Animal a new Dog(); System.out.println(a.age); } } class Animal{ int age 5; } class Dog extends Animal{ int age 1; }运行结果解释说明编译看左边编译器检查 Animal 类里有没有 age有编译通过。运行看左边实际运行拿到的值也是 Animal 类里的 5。2、调用成员方法编译看左边运行看右边。场景演示public class Test { public static void main(String[] args) { Animal a new Dog(); a.eat(); // a.watchDoor(); } } class Animal{ public void eat(){ System.out.println(动物在吃东西); } } class Dog extends Animal{ Override public void eat(){ System.out.println(狗在啃骨头); } public void watchDoor(){ System.out.println(狗在看门); } }运行结果解释说明编译看左边Animal 里有 eat() 方法吗有编译通过。运行看右边实际对象是 DogDog 重写了 eat()执行 Dog 的逻辑。编译看左边Animal 里有 watchDoor() 方法吗没有直接报错红线3、邪修理解方式成员变量假设Dog穿上了Animal的制服向上转型。这件Animal制服的胸口挂着一个名牌成员变量上面写着“年龄5岁”。 当你编译器/JVM去读取它的年龄时你只认制服不认人。你看到制服上写着什么读出来的就是什么。哪怕里面这只狗实际上只有 1 岁你也不管。成员方法还是那只穿了Animal制服的Dog。编译看左边检查权限你命令它“去吃东西”。编译器会先看它穿的Animal制服手册里有没有“吃东西”这个动作。如果有允许你下达命令编译通过。如果没有编译器直接报错“动物制服没这个功能不许叫它做”。运行看右边实际执行命令下达后真正在执行动作的是制服里面的那只Dog。狗有自己独特的吃法啃骨头所以它会按照狗的方式去吃而不是用普通动物的方式吃。