> 文档中心 > 【基础篇】java的多态到底是什么?(详细案例逐步分析)

【基础篇】java的多态到底是什么?(详细案例逐步分析)

哈喽,大家好!我是Why,一名在读学生,目前刚刚开始进入自己的编程学习生涯。虽然学习起步较晚,但我坚信做了才有0或1的可能。学了一段时间以后也是选择在CSDN上分享自己的日常笔记,也希望能够在众多道友的大家庭中打成一片。
本文主要讲解🌈java的多态🌈如果大家读后觉得有用的话,还请大家多多支持博主:欢迎 ❤️点赞👍、收藏⭐、留言💬
✨✨✨个人主页:java-WangHY

文章目录

  • 🌾概念
    • ✨前提引入
      • 🍎向上转型
      • 🍎向下转型
      • 🍎instanceof 运算符
        • 🎯使用说明
        • 🎯注意:
        • 🥝好处:
    • 💎基础语法
      • 🏓多态语法实例
      • 🐳案例—为什么要用 if instanceof ?
    • 🤡写在最后

🌾概念

多态,简单来说就是一种事物的多种形态。在java中即指一个实体在不同时刻代表的对象可能不一样。

原因在与对象都是引用数据类型。可以理解为父类型的引用指向了子类型的对象,或者是接口的引用指向接口实现类的对象。

举一个栗子,当你考试的时候有一个问题让你随便写一个动物的名字,此时,你写熊猫也好,长颈鹿也罢,只要它属于动物就行,这就是最基本的“多态”。再进一步,这些动物都要进食,我们就可以把进食设置为一个方法,但是每种动物的进食方法不一样,那这个就可以设置每个动物进食的特征。这样当我们说的动物不相同的时候,虽然使用了所有动物的特性——进食,但是又能把进食这个行为描述的更具体。
【基础篇】java的多态到底是什么?(详细案例逐步分析)

✨前提引入

🍎向上转型

子 —> 父(自动类型转换)

🍎向下转型

父 —> 子(强制类型转换,需要加强制类型转换符)

不要随便做强制类型转换。
当你需要访问的是子类对象中“特有”的方法,此时必须进行向下转型

🍎instanceof 运算符

🎯使用说明

第一:instanceof可以在运行阶段动态判断引用指向的对象的类型。
第二:instanceof的语法:
(引用 instanceof 类型)
第三:instanceof运算符的运算结果只能是:true/false
第四:a是一个引用,a变量保存了内存地址指向了堆中的对象。
假设(a instanceof A)为true表示:
a引用指向的堆内存中的java对象是一个A
false表示:
a引用指向的堆内存中的java对象不是一个A

🎯注意:

任何时间,对类型进行向下转型时,一定要使用
instanceof 运算符进行判断

🥝好处:

使用该关键字都可以避免ClassCastException异常

💎基础语法

1、包括编译阶段和运行阶段:

编译阶段:绑定父类的方法。
运行阶段:动态绑定子类型对象的方法。

简单来说就是编译阶段的类型是父类的,但是实际在运行的时候最终调用了子类的方法

也可以理解为:

多态表示多种形态:

编译的时候一种形态。
运行的时候另一种形态。

2、易错点:

多态情况下,子父类存在同名的成员变量或者静态成员方法的时候,访问的都是父类成员的变量或者方法

存在同名的非静态的成员方法的时候,访问的是子类的成员方法

3、使用场景

继承关系 满足 is a ;例如:A is a B!
实现关系 满足 has a ;例如:A has a B!
有方法的覆盖

4、好处

提高程序的扩展性
降低程序的耦合度
可以将所有的对象都看做是父类的,进而屏蔽了不同子类对象之间的差异性

🏓多态语法实例

package com.blog;/** * @author 尽欢 */public class Test{    public static void main(String[] args) { //之前创建对象 Animal animal01 = new Animal(); Cat cat01 = new Cat(); Dog dog01 = new Dog(); Pig pig01 = new Pig(); //学了多态以后创建对象 为什么可以这样? 因为有继承关系,满足 is a //切记,是父类型的引用    指向  子类型的对象 Animal a1 = new Cat(); Animal a2 = new Pig(); //能不能这样呢?不可以 为什么?因为二者没有继承关系 is a虽然说的通,但是有继承关系这个前提不满足 //Animal a3 = new Dog(); /**  * 多态之间的转换  *      向上转型以及乡下转型  * */ //此时创建一个Animal对象,底层实际上是一只猫咪 Animal a4 = new Cat(); //调用子类继承过来的方法会是什么结果呢?执行子类重写的方法 a4.eat();//猫咪在吃鱼! /* 分析一下:   java程序分为编译阶段和运行阶段。     编译阶段:  对于编译器来说,编译器只知道a4的类型是Animal类型  编译器发现该对象要调用 eat这个方法,就会去Animal的  类文件中找eat()方法,找到了对应的eat方法,直接绑定,  静态绑定成功  编译通过,而后进入运行阶段     运行阶段:  a4这个引用实际上指向了在堆内存中创建的Cat对象,  所以eat的时候,真正实现该方法的实际上是该Cat对象  所以运行阶段会动态执行Cat对象的eat()方法  动态绑定成功 */ // 那么能否调用猫咪独有的方法呢? 不能! //a4.fish(); 报错了,为什么?这个引用不是实际指向了cat对象吗?为什么不能调用呢? /*  * 继续分析:  *      程序运行时,第一步,编译成class文件  *      编译阶段,编译器发现a4是一个Animal类型的对象  *      该对象要调用 fish() 这个方法————这也叫静态绑定  *      于是就去Animal的类文件中寻找该方法  *    结果没有找到,显示错误,直接编译失败  *      程序退出  */ //那么怎么调用猫咪独有的方法呢?   向下转型 Cat newCat = (Cat) a4; /* 向下转型需要注意什么?   注意转换类型 下面两行代码并没有报错,也就是说这样写实际上是“合法”的,因为编译器没有给我们警告提示 虽然我们知道a4实际上是一个猫咪。但是我们却可以直接强转为猪猪, 猪猪和猫咪之间又没有继承关系,这显然是不合理的,但是为什么就是能转换成功呢?    因为编译阶段的 a4 是一个Animal类型  Animal和Pig有没有及成果关系?  有    所以能转换    但是编译阶段,什么情况!一个猪类型的引用怎么想要指向猫类型的对象?    赶紧报错!!于是出现这个异常:    java.lang.ClassCastException:类型转换异常 */ Pig newPig = (Pig) a4; newPig.sleep(); //怎么避免这类异常呢? //instanceof关键字 if(a4 instanceof Pig){     //进来了说明a4就是一个猪猪类型的对象     Pig realPig = (Pig) a4; }    }}/** * 动物类:父类 * */class Animal{    /**     * 所有动物的默认进食方法     * */    public void eat(){ System.out.println("动物在吃东西!");    }}/** * 猪猪类:动物类的子类 * */class Pig extends Animal {    @Override    /**     * 重写父类的方法     * */    public void eat() { System.out.println("猪猪在吃白菜!");    }    /**     * 自己独有的方法     * */    public void sleep(){ System.out.println("猪猪在睡觉!");    }}/** * 猫咪类:动物类的子类 */class Cat extends Animal {    /**     * 重写父类的方法     * */    @Override    public void eat() { System.out.println("猫咪在吃鱼!");    }    /**     * 自己独有的方法     * */    public void fish(){ System.out.println("猫咪在捕鱼!");    }}/** * 狗狗类:没有继承动物类 * */class Dog {    /**     * 自己独有的方法     * */    public void play(){ System.out.println("狗狗在摇尾巴!");    }}

🐳案例—为什么要用 if instanceof ?

package com.blog;/** * @Author jinhuan * @Date 2022/3/23 12:46 * Description: */public class instanceofTests {    /**     *     * 有时候我们往往站在一个上帝视角去看问题     * 比如我们以为明明知道狗狗就是一个动物,那么为什么还要去判断类型呢?     * 其实实际的开发中大多都是团队合作,到底底层传递来的是什么类型的数据,有时候我们真的不知道     *     * */    public static void main(String[] args) { test(new Cat()); test(new Pig()); test(new Dog()); test(new Animal());    } /*     * 假设程序员A在调用的test方法的时候,由于并不知道具体传递的是什么类型     * 但是知道是一个动物,要求我们对test方法进行扩展     * 使得:     *      如果test接收的对象有自己独有的方法时,展示其独有的方法     *      如果没有的话就展示动物都具有的方法     */ /*原方法 static void test(Animal animal){     animal.eat(); }    */    /**     * 扩展后的方法    * */    static void test(Animal animal){ if(animal instanceof Cat){     ((Cat) animal).fish(); }else if(animal instanceof Dog){     ((Dog) animal).play(); }else if(animal instanceof Pig){     ((Pig) animal).sleep(); }else {     animal.eat(); }    }}class Animal{    public void eat(){ System.out.println("动物在吃东西!");    }}class Dog extends Animal{    @Override    public void eat(){ System.out.println("狗狗在啃骨头!");    }    public void play(){ System.out.println("狗狗在摇尾巴!");    }}class Pig extends Animal{    @Override    public void eat() { System.out.println("猪猪在吃白菜!");    }    public void sleep(){ System.out.println("猪猪在睡觉!");    }}class Cat extends Animal{    @Override    public void eat() { System.out.println("猫咪在吃鱼!");    }    public void fish(){ System.out.println("猫咪在捕鱼!");    }}

【基础篇】java的多态到底是什么?(详细案例逐步分析)

🤡写在最后

以上均为本人个人观点,借此分享。如有不慎之处,劳请各位批评指正!鄙人将不胜感激并在第一时间进行修改!另外,我自己整理了一些资源(笔记、书籍、软件等)分享在我的公众号上,非常欢迎大家来访白嫖和博主做朋友,一起学习进步!最后别忘啦支持一下博主哦,求三连!❤️❤️❤️

【基础篇】java的多态到底是什么?(详细案例逐步分析)

【基础篇】java的多态到底是什么?(详细案例逐步分析)

推币机的世界