【Java】多态

发布时间:2026/9/27 22:51:59

【Java】多态 多态知识点多态的概念通俗同一件事不同对象去做产生不同结果例子动物都有eat()行为猫 eat 是吃鱼狗 eat 是吃骨头Java 实现多态的 3 个必要条件必须存在继承关系子类 extends 父类子类重写 (override) 父类的方法父类引用指向子类对象用父类引用调用重写后的方法补充多态的特点编译看父类运行看子类编译阶段编译器只认识父类类型运行阶段看引用实际指向的子类对象执行子类重写后的方法代码public class Animal { String name; int age; //构造方法 public Animal(String name,int age) { this.namename; this.ageage; } //父类方法 public void eat() { System.out.println(name吃饭); } }public class Cat extends Animal{ //由于父类写了代参构造那么子类也得构造一下父类的 public Cat(String name,int age) { super(name,age); } //重写父类方法 Override public void eat() { System.out.println(name吃鱼); } }public class Dog extends Animal{ public Dog(String name,int age) { super(name,age); } Override public void eat() { System.out.println(name啃骨头); } }//形参是父类Animal 父类引用可以接收任意子类对象多态核心 public static void eat(Animal a) { a.eat(); } public static void main(String[] args) { Cat catnew Cat(菊花猫,1); Dog dognew Dog(小黄,2); eat(cat); //传入Cat对象运行调用Cat中的eat eat(dog); //传入Dog对象运行调用Dog中的dog }调用者写eat(Animal a)方法时不需要关心传进来是猫还是狗只要是 Animal 子类都能传入运行自动匹配子类实现这就是多态带来的好处代码通用、易扩展重写方法重写Override / 覆盖定义子类重新实现父类的方法外壳方法名、参数不变只改内部方法体重写规则方法原型基本一致方法名、参数列表必须完全一样a返回值可以不一样但必须是父子类关系协变返回类型面试考点访问权限不能更严格a父类如果是public子类不能写成protected/private权限可以放宽例父类 protected子类可以 public不能重写的方法astatic静态方法、private私有方法、final方法、构造方法Override注解a显式标记这是重写编译器帮我们校验语法b如果方法名拼写错误比如把 eat 写成 aet直接编译报错防止写错重写 和 vs 重载总结a重载同一个类同名不同参数属于编译期多态b重写子类继承父类同名同参数属于运行时多态c方法重载是一个类的多态方法重写是子类与父类之间的多态public class Father { //方法重载 - 同一个类里方法名相同参数不同 public void say() { System.out.println(父亲说话无参数); } public void say(String world) { System.out.println(父亲说话world); } // 给子类继承的方法 public void work() { System.out.println(父亲的工作上班打工赚钱); } }public class Son extends Father{ //方法重写 -》 方法名参数列表完全相同 Override public void work() { System.out.println(儿子的工作上班敲代码); } }public static void main(String[] args) { Father fnew Father(); //调用 重载根据参数不同配备不同的方法 f.say(); f.say(我是Father); // 重写 Son sonnew Son(); son.work(); //多态的写法-- 父类引用指向子类对象 Father f1new Son(); f1.work(); //运行时 执行子类Son 里边的work 方法是动态绑定 Father f2new Father(); f2.work(); }重载Overload1同一个类2方法名一样3参数列表不一样4返回值、访问修饰符随便改5编译期就确定调用哪个方法 → 静态绑定6调用时看你传不传参数编译器直接选对应的方法重写Override1在父子两个类2方法名、参数列表完全一模一样3子类权限不能比父类更严格4运行时才确定调用哪个方法 → 动态绑定向上转型 和 向下转型向上转型自动类型转换定义子类对象当成父类对象来使用小范围 → 大范围自动转换语法父类类型 对象名 new 子类类型(); // 示例 Animal animal new Cat(元宝,2);使用场景1直接赋值子类对象直接赋值给父类引用2方法传参形参写父类类型可以接收任意子类对象3方法返回值返回值类型写父类可以返回任意子类对象特点1优点代码灵活统一编程多态的基础2缺陷父类引用只能调用父类的方法不能调用子类独有的方法如果子类重写了父类方法执行时会运行子类重写后的方法向下转型强制类型转换向上转型之后父类引用无法访问子类特有方法如果需要调用子类独有方法就要把父类引用强制转回子类类型就是向下转型语法子类类型 对象名 (子类类型)父类引用;向下转型不安全1如果父类引用实际指向的不是该子类对象编译不报错但运行抛出ClassCastException类型转换异常2Animal animal new Dog(); Cat cat (Cat) animal; // 运行报错animal本质是狗不能强转为猫安全方案instanceof1作用判断对象的真实类型是不是后面这个类返回布尔值2只有 instanceof 判断为 true才进行强制向下转型避免运行异常3if(animal instanceof Cat){ Cat cat (Cat) animal; cat.mew(); // 调用猫独有方法 } if(animal instanceof Dog){ Dog dog (Dog) animal; dog.bark(); // 调用狗独有方法 }常见面试题1向上转型什么时候发生直接赋值、方法传参、方法返回自动发生2向上转型后调用方法执行父类还是子类编译看左边父类有没有这个方法运行看右边对象真实是子类 执行子类重写方法3向下转型为什么要加 instanceof防止运行时ClassCastException类型转换异常总结1向上转型拿父类的壳装子类的东西只能看见父类的方法执行时跑子类重写方法2向下转型把壳拆回去变回子类才能调用子类独有的方法拆错了就崩所以先用instanceof判断代码public class Animal { private String name; private int age; //构造方法 public Animal(String name,int age) { this.namename; this.ageage; } 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 eat() { System.out.println(动物在吃东西); } public void sleep() { System.out.println(动物在睡觉); } }public class Dog extends Animal{ public Dog(String name,int age) { super(name,age); } //重写父类中的eat 方法 Override public void eat() { System.out.println(getName()小狗在啃骨头); } // 子类 Dog 中独有的方法 public void bark() { System.out.println(getName()汪汪); } }public class Cat extends Animal{ public Cat(String name,int age) { super(name,age); } //重写父类中的 eat方法 Override public void eat() { System.out.println(getName()猫在吃鱼); } //子类 Cat 中独有的方法 public void mew() { System.out.println(getName()喵喵); } }// 方法传参 - 形参为父类Animal ,可以接收任意子类对象 public static void eatFood(Animal a) { a.eat(); } //作为返回值- 返回任意子类对象 public static Animal buyAnimal(String var) { if(狗.equals(var)) { return new Dog(狗狗,1); } else if(猫.equals(var)) { return new Cat(猫猫,1); } else { return null; } }直接赋值子类对象赋值给父类引用向上转型向下转型补充Animal父类Cat、Dog两个子类都重写了eat()并且各自有独有的方法mew()/bark()向上转型Animal cat2 new Cat(元宝,2);1父类引用指向子类对象只能调用父类存在的方法执行时运行子类重写逻辑2无法直接调用子类独有方法向下转型想要调用mew()/bark()必须强制转回子类类型instanceof判断对象真实类型避免ClassCastException类型转换异常多态的有缺点多态public class Shape { //给子类继承的方法 public void draw() { System.out.println(图形); } }public class Cycle extends Shape { Override public void draw() { System.out.println(圆形); } }public class Rect extends Shape{ Override public void draw() { System.out.println(菱形); } }public class Flower extends Shape{ //重写父类方法 Override public void draw() { System.out.println(花); } }public class test { public static void drawShapes() { //父类数组存放子类对象多态 Shape[] shapes{new Cycle(),new Flower(),new Rect()}; for(Shape shape:shapes) { shape.draw(); } } public static void main(String[] args) { drawShapes(); } }Shape 是父类Rect、Cycle、Flower 是子类都重写了draw()方法父类引用指向子类对象就是多态多态的好处降低代码圈复杂度消除大量if-else1) 圈复杂度衡量代码复杂程度分支 / 循环越多越复杂项目规范一般要求圈复杂度≤10不使用多态大量 if-elsepublic static void drawShapes() { Rect rect new Rect(); Cycle cycle new Cycle(); Flower flower new Flower(); String[] shapes {cycle, rect, cycle, rect, flower}; for (String shape : shapes) { if (shape.equals(cycle)) { cycle.draw(); } else if (shape.equals(rect)) { rect.draw(); } else if (shape.equals(flower)) { flower.draw(); } } }新增图形时必须继续增加else if代码越来越臃肿使用多态1不需要任何 if 判断同一个方法draw()不同对象调用产生不同行为public static void drawShapes() { // 父类数组存放各个子类对象 Shape[] shapes {new Cycle(), new Rect(), new Cycle(), new Rect(), new Flower()}; for (Shape shape : shapes) { shape.draw(); // 自动调用对应子类重写的draw方法 } }可扩展性强新增类改动成本低1新增三角形Triangle只需要写一个继承Shape的类并重写draw()public class Triangle extends Shape{ Override public void draw() { System.out.println(三角形); } }2多态方式调用方drawShapes完全不用修改只需要往数组加new Triangle()3非多态 if-else 方式必须修改drawShapes新增 else if 分支4符合开闭原则对扩展开放对修改关闭多态的缺点父类引用不能直接访问子类独有的方法 / 属性需要强制类型转换运行时绑定相比静态编译会有微小性能开销现代 JVM 基本可忽略避免在构造方法中调用重写的方法结论1构造方法执行期间子类对象还没初始化完成2如果调用了可重写方法会触发动态绑定执行子类重写后的代码3子类方法里访问子类成员变量时变量还没赋值拿到的是默认值产生诡异 bug不要在构造方法中调用可以被子类重写的方法普通 public/protected 实例方法补充1子类对象构造先父构造再子类成员初始化2父构造里调用可重写方法会提前跑到子类重写方法此时子类变量还是默认值解决方法1构造方法里可以调用 private / final 方法因为这两类方法不能被子类重写不会触发动态绑定就不会有这个坑2private 方法不能重写无动态绑定aprivate方法只能在当前类内部使用子类不能重写b父类构造器中调用的func()永远是 B 自己的方法不会跑到子类 D 的 func不会出现变量未初始化问题3final 方法不能重写无动态绑定afinal修饰实例方法禁止子类 Override 重写b父类构造里调用 func一定执行 B 自己的 func不存在多态动态绑定不会调用子类代码c) 如果强行写 Override 重写 final 方法直接编译失败总结private私有子类根本看不见不能重写静态绑定final上锁不允许子类重写静态绑定public/protected普通方法可重写动态绑定父构造调用会执行子类重写方法此时子类成员还没初始化有坑
延伸阅读

更多相关文章

2026/9/27 22:51:59

高频核心硬件面试2026—通用电子方向深度精讲

本文为专栏内部精讲内容,聚焦硬件工程师面试中最具区分度的高频问题,每题配套考察点剖析、标准解法、易错项提醒、工程案例与关键计算,帮助读者在2026届招聘季中展现系统级工程思维与实战功底。 对于硬件工程师而言,面试是展现技术深度、工程严谨性与问题解决能力的核心舞…

2026/9/27 22:51:59

140、提示词优化工具:ChainForge等

140、提示词优化工具:ChainForge等 上午十一点,线上客户反馈知识库问答开始胡说八道。我拉出日志一看,排在最前面的答案居然把“订单未支付”理解成了“申请退款”,而我们的prompt里明明写了“请判断用户意图”。这已经不是第一次了——上一周还在为模型能记住多轮对话而高…

2026/9/27 22:46:59

Windsurf+MCP 配 TaoToken:settings.json 骨架与报错排查实录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/27 23:42:02

温州论坛703源码避坑指南:保姆级建站教程揭秘

温州论坛703源码避坑指南:保姆级建站教程揭秘 别被那些花里胡哨的模板网站骗了,看着挺像回事,用起来全是坑,尤其是像【温州论坛703】这种带特定地域属性或特定板块结构的旧源码,很多新手直接拿去改,结果上线才发现样式错乱、后台权限混乱,简直比…

2026/9/27 23:37:02

网站建设mingxinsh避坑指南:看懂建站报价才敢开工

网站建设mingxinsh避坑指南:看懂建站报价才敢开工 网站做好了没人访问,这是很多老板做网站后最头疼的事。你花了大几千甚至几万块钱,网站上线了,每天后台看流量只有个位数,心里直打鼓:这钱是不是打水漂了?别急,这通常不是技术问题,而是你在…

2026/9/27 0:00:45

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/27 0:00:45

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/27 0:00:45

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/27 0:00:45

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/27 0:00:45

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/27 0:00:45

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/25 20:55:38

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/26 19:58:38

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/25 18:34:56

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑