尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Java面向对象三大特征之--多态
前言前面我们已经学习了封装、继承两大特征今天我们来学习面向对象的三大特征中的最后一个特征多态。废话不多说让我们一起开始吧目录一、向上转型和向下转型1.1 向上转型自动类型转换1.1.1 定义1.1.2 写法1.1.3 特点1.1.4 能调用什么1.1.5 限制1.2 向下转型强制类型转换1.2.1 定义1.2.2 写法1.2.3 缺陷与解决方法1.2.4 作用二、多态2.1 多态的概念2.2 多态的写法2.3 多态的实现条件三、方法重写3.1 重写的本质3.2 重写的概念3.3 重写的规则3.4 和多态的关系四、静态绑定和动态绑定4.1 概念4.2 静态绑定早绑定4.3 动态绑定晚绑定4.4 浓缩口诀4.5 代码示例五、多态的优缺点5.1 优点5.2 缺点一、向上转型和向下转型在讲多态之前我们需要先学一下向上转型和向下转型因为多态需要用到向上转型。1.1 向上转型自动类型转换1.1.1 定义父类引用接收子类对象。自动转换不用强转。代码示例1.1.2 写法父类类型 引用名new 子类类型();1.1.3 特点自动完成不用写任何强制符号1.1.4 能调用什么编译看左边父类只能调用父类里面定义的方法如果子类重写了这个方法运行看右边执行子类重写的代码这就是多态1.1.5 限制父类引用不能直接访问子类独有的成员变量和成员方法只能调用父类自己的。编译看左边父类引用只能看到父类中定义的成员成员方法、成员变量子类新增的成员变量新增的成员方法哪怕真实对象是Dog父类引用都不能直接访问编译直接报错。1.2 向下转型强制类型转换1.2.1 定义已经向上转型后的引用强制转回子类类型需要手动强转。代码示例注意点上述代码中的animal这个引用虽然进行了强转但是animal这个引用本身类型永远不变它始终是Animal类型向下转型Dog dog(Dog) animal;不是把animal改造了而是新建了一个Dog类型的引用变量dog让它指向同一个对象。所以animal依旧不能直接访问子类独有的成员⬇1.2.2 写法子类类型 引用名子类类型父类引用名1.2.3 缺陷与解决方法必须手动写Dog强制转换有风险⚠当项目代码多、有很多父类引用各自指向不同子类。时间久了你不能一眼看出来某个Animal用用底层到底装的是哪个子类对象凭感觉直接强转Dog类型如果这个引用实际对象的对应类型不是Dog运行直接抛出ClassCastException类型转换异常。Java中为了提高向下转型的安全性引入了instanceof如果该表达式为true则可以安全转换⬇如果表达式是false则if里面的强制类型转换的代码块不会执行就不会发生类型转换异常⬇1.2.4 作用转完之后就可以调用子类独有的成员了。是通过新的dog引用调用不是animal。二、多态2.1 多态的概念多态通俗来说就是多种形态同一个行为不同对象有不一样的实现形式。父类定义方法各个子类重写该方法使用父类引用指向不同的子类对象调用这个方法时会自动执行对应子类重写后的版本呈现不同的行为。比如同样是“叫”这个行为狗是“汪汪叫”猫是“喵喵叫”鸭子是“嘎嘎叫”我们统一有一个动物父类里面定义了 叫() 这个行为。狗、猫、鸭子都是动物的子类各自重写了叫的方法。变量的类型是动物父类但它实际是一只狗子类。同样一句叫() 对象不同表现出来效果不一样这就是多态。代码示例2.2 多态的写法父类类型 引用变量new 子类类型();比如Animal animal new Dog();父类引用指向子类对象。调用 animal.叫() 实际执行的是Dog里面的叫方法。父类引用指向子类对象调用同一个方法看右边实际对象执行子类重写后的代码。2.3 多态的实现条件①必须在继承体系下②子类必须要对父类中方法进行重写③通过父类的引用调用重写的方法三、方法重写在继承那篇我们已经讲过了方法重载和方法重写两个易混淆的概念今天我们再来温故而知新一下方法重写因为它是实现多态关键。3.1 重写的本质子类覆盖父类用一个实例方法配合多态父类引用调用时执行子类的逻辑。3.2 重写的概念重写(Override)也就称为覆盖。重写是子类对父类非静态、非private修饰非final修饰非构造方法等的实现过程进行重新编写。返回值和形参都不能改变。即外壳不变核心重写。重写的好处在于子类可以根据需要定义特定于自己的行为。也就是说子类能够根据需要实现父类的方法。为啥不能重写静态方法、private修饰的方法final修饰的方法构造方法①. static 静态方法不能重写静态方法属于类不属于对象编译阶段就绑定好了。父类静态方法跟着父类子类同名静态方法跟着子类二者互不覆盖这叫隐藏不是重写。多态是基于对象的机制静态和对象无关自然不存在重写。②. private 私有方法不能重写private 方法只在本类内部可见子类根本看不到这个方法。子类写一个一模一样名字、参数的方法只是子类新建了一个属于自己的全新方法并没有覆盖父类的私有方法。看不见就谈不上重写。③. final 修饰的方法不能重写final 关键字作用就是锁定这个方法禁止子类覆盖修改实现。只要父类方法加了final编译器直接拦截子类不能写同名同参数的重写方法。注意final修饰方法只是禁止重写父类本身仍然可以被继承。④. 构造方法不能重写构造方法名字必须和当前类名完全相同。父类Animal构造名叫 Animal() 子类Dog构造名叫 Dog() 。重写要求方法名、参数列表一致名字都不一样直接不满足重写最基础的条件。子类构造方法的 super() 只是调用父类构造不是重写。3.3 重写的规则①.子类在重写父类的方法时方法名参数列表必须与父类原型保持一致。②.子类在重写父类的方法时返回值类型如果是基本数据类型(int、double等)就必须与父类保持一致父类返回int子类重写只能是int。如果返回值类型是引用类型(类/接口)那子类重写的方法返回值类型可以和父类不同但是必须是父类方法返回类型的子类比如父类方法返回类型为A子类重写的返回类型只能是A或者是A的子类。③子类重写的父类方法的访问权限要大于等于父类原本的方法比如如果父类方法被public修饰则子类中重写该方法就不能写protected。④父类被static、private、final修饰的方法构造方法都不能被重写。⑤重写的方法可以使用Override注解来显示指定有了这个注解就能帮助我们进行一些合法性校验例如不小心将方法名字拼写错了比如写成aet那么此时编译器就会发现父类中没有aet方法就会编译报错提示无法构成重写。如果不加Override注解⬇不加 Override 的隐患当我们打算重写父类方法不小心写错方法名/参数列表时代码可以正常编译、正常运行不会报任何错误。程序会把它当成子类新增的独立方法。我们主观上以为完成了重写实际上没有后续使用多态的时候就会出现不符合预期的结果这种隐性逻辑bug很难排查。加上Override注解⬇加上 Override 注解后在编写代码、编译阶段就能直接看到报错提示不需要等到程序运行之后。IDEA 在 Override 注解上标出波浪下划线提醒我们当前这个方法并没有重写父类的对应方法说明我们写重写的时候出错了。Override 的意义就是提前校验在运行代码之前就发现重写的错误避免出现能正常运行但逻辑不符合预期的隐性bug。3.4 和多态的关系方法重载是一个类的多态性表现方法重写是子类与父类的一种多态性表现。四、静态绑定和动态绑定4.1 概念[绑定]:绑定是指方法调用和方法本体配对的过程静态绑定编译阶段就确定调用哪个方法。动态绑定运行阶段才确定调用哪个方法Java多态底层考的就是动态绑定。4.2 静态绑定早绑定在编译的时候编译器根据引用变量的类型左边的类型直接确定调用哪个方法。在编译器就绑定运行的时候不变。适用静态方法private修饰的方法final修饰的方法构造方法。静态绑定不支持多态。4.3 动态绑定晚绑定编译时只看引用类型运行的时候看对象真实类型new出来的右边类型再去找对应的重写方法。这就是多态的底层原理。如果没有动态绑定向上转型后就永远只能执行父类的方法就不存在多态。只有实例方法重写才会触发动态绑定才有多态效果。适用只有普通实例方法可以被重写的方法才会触发动态绑定。4.4 浓缩口诀静态绑定编译看左运行也看左没有多态。动态绑定编译看左运行看右实现多态。4.5 代码示例五、多态的优缺点5.1 优点①. 代码扩展性好。以后新增子类不用改原来写的调用代码。比如现在AnimalDog、Cat后面再加Pigmain里面调用animal.eat()那一行完全不用动直接新加类就行符合开闭原则。②. 降低代码耦合。调用方只需要认识父类不用关心具体是哪个子类不需要依赖子类细节。[什么是耦合]耦合就是代码和代码之间邦得有多紧。假设我写一段代码专门去喂狗Dog dog new Dog();dog.eat();这段代码直接写死依赖Dog类。如果以后我想改成喂猫你就得回来改这行代码把Dog换成Cat。调用代码跟Dog紧紧绑在一起这就叫耦合高。用多态之后Animal animal new Dog();animal.eat();调用代码只认识父类Animal它根本不管后面是Dog、Cat还是Pig。想换成猫只需要右边改成 new Cat() 调用那一行 animal.eat() 完全不用改。调用代码不依赖具体子类耦合低。③. 代码简洁复用性强。可以统一写一套父类的调用逻辑不同子类自动执行自己重写的方法不用写一堆if判断去区分是什么动物。5.2 缺点①. 向上转型之后不能直接调用子类独有的方法。比如 Animal animal new Dog(); animal不能直接调用Dog里面独有的watchDoor()想用的话得向下转型强转强转还容易抛出类型转换异常有风险。②. 运行的时候才确定执行哪个方法调试稍微麻烦一点。读代码的时候光看变量类型看不出实际执行哪个方法。六、总结本篇我们一起学习面向对象的最后一个特性--多态并且通过多态延伸出了其他的知识向上(下)转型、方法重写、静态绑定动态绑定最后总结了多态的优缺点。欢迎大佬在评论区指出错误。我将持续更新学习笔记哦~我们下篇再见拜拜
RELATED

相关推荐

大模型技术深度解析:小白程序员必看!收藏学习路径,抓住未来风口

大模型技术深度解析:小白程序员必看!收藏学习路径,抓住未来风口

本文深入解析了2026年上半年AI大模型的混战格局与策略展望。主要内容包括:Scaling Law的新方向(多模态、Multi-agent、RSI递归自我改进),前沿模型(Frontier model)的竞争态势,价格战&#xff08…

📅 2026/10/16 9:27:32
建冷库还要找好几家供应商?一站式配套有多省心

建冷库还要找好几家供应商?一站式配套有多省心

很多人第一次建冷库会踩坑:库板找一家、冷库门找一家、制冷机组再找另外一家。多方对接沟通成本高,设备之间还容易出现不匹配的情况,出问题几家互相推卸责任。月宫冷冻可以提供一条龙配套,冷库用到的库板、冷库门、压缩机组等核心…

📅 2026/10/16 9:27:32
Agent 调用省 Token 实战指南:提示词、Skill 精简、Memory 压缩与场景取舍

Agent 调用省 Token 实战指南:提示词、Skill 精简、Memory 压缩与场景取舍

本文收录于专栏 AI Agent智能体系列 —— 专栏系统覆盖 AI Agent 的架构、工具调用、记忆与成本工程实战,点击订阅可跟踪后续更新。 你的 Agent 跑一天,账单烧掉几十万 Token,大头不在「思考」而在「复读」——每一轮都要把系统提示词、工具定…

📅 2026/10/16 9:27:32
MORE NEWS

更多资讯

📰

通话回声排查指南:问题常在对方那头,三分钟定位法

你有没有遇过这种场面:电话那头的人一直在喊“喂?喂?听得到吗?”你这边也在喊“听得到,你说”,可每次你一停下来,过个一两秒,自己的声音就像碰上山壁一样,又从听筒里折回…

📰

Docker微服务架构实战:从拆分逻辑到容器化治理与避坑指南

简介:这份《Docker微服务架构实战》PDF面向云计算与后端开发从业者,尤其是正在推进架构演进的中小型企业团队,帮助解决微服务拆分、容器化部署与DevOps整合中的落地难题。全书由高级架构师蒋彪撰写,围绕微服务技术选型、服务拆分原…

📰

产品经理如何提升不可替代性?四大落地方法告别需求传话筒

“这个需求很简单,怎么实现我不管,下个版本就要上线。”——说这话的时候,有没有想过,你在团队眼里到底是“业务翻译机”,还是一个随时可以被替换的“需求传话筒”?我见过太多产品经理,工作三五…

📰

C语言指针与字符串深度解析:哈工大练兵题实战指南

1. 从一道练兵题看C语言指针与字符串的深层逻辑哈工大2020年C语言程序设计精髓这门课,在编程学习者圈子里口碑一直很硬。它的练兵区题目有个特点:看起来要求简单,但真正动手写的时候,你会发现每一道题都在逼你理解底层机制&#x…

📰

C++ deque底层原理与queue/stack容器适配器实战

1. 从一次性能翻车说起:为什么我要重啃 deque 底层去年帮一个做实时数据采集的朋友排查性能问题,场景很简单:一个生产者线程往队列里塞数据,一个消费者线程从队列里取数据,中间用std::queue做缓冲。按理说这种模式跑个…

📰

C# OPC DA客户端开发实战:COM互操作与工业数据采集

简介:本资源是一份基于C#与OPCDAAuto.dll实现的OPC客户端示例工程,面向从事工业自动化上位机开发、需要与OPC DA服务器进行数据交互的C#开发者,尤其适合刚接触COM组件调用与OPC通信的初中级人员参考。压缩包共58个文件,约223KB&am…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬