当前位置: 首页 > news >正文

Java面向对象:继承与多态

Java面向对象:继承与多态

1. 引入:为什么需要继承?

1.1 代码重复的问题

假设你要定义两个类:学生和老师。

classStudent{privateStringname;privateintage;privateStringstudentId;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}}classTeacher{privateStringname;privateintage;privateStringteacherId;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}}

问题:name和age相关的代码写了两遍,如果以后要加一个字段,两个类都要改。

1.2 继承的解决方案

把公共的部分抽取到父类中:

// 父类classPerson{privateStringname;privateintage;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}}// 子类继承父类classStudentextendsPerson{privateStringstudentId;// 自己独有的属性}classTeacherextendsPerson{privateStringteacherId;// 自己独有的属性}

子类自动拥有了父类的属性和方法,代码复用,维护也方便。


2. 继承的基本概念

2.1 继承的格式

class子类extends父类{// 子类自己的成员}

2.2 继承的特点

特点说明
单继承Java只支持单继承,一个子类只能有一个父类
多层继承可以有多层,如A→B→C,C继承B的,B继承A的
所有类都继承Object如果没写extends,默认继承Object类

2.3 继承的优点和缺点

优点

  • 代码复用,减少重复
  • 便于维护(改父类,子类自动生效)
  • 为多态打下基础

缺点

  • 父子类耦合度高(父类改了,子类可能受影响)
  • 破坏了封装(子类可以访问父类的protected成员)

3. 继承中成员变量的访问

3.1 不同名变量

子类和父类变量名不同,直接访问就行:

classFather{intmoney=100;}classSonextendsFather{intcar=1;voidshow(){System.out.println(money);// 100,继承来的System.out.println(car);// 1,自己的}}

3.2 同名变量(就近原则)

子类和父类变量名相同时,优先用子类的:

classFather{intscore=80;}classSonextendsFather{intscore=95;voidshow(){intscore=100;System.out.println(score);// 100(局部变量)System.out.println(this.score);// 95(子类成员)System.out.println(super.score);// 80(父类成员)}}

3.3 super关键字

super用来访问父类的成员:

用法说明
super.成员变量访问父类的成员变量
super.成员方法访问父类的成员方法
super()调用父类的构造方法

4. 继承中成员方法的访问

4.1 方法重写(Override)

子类可以对父类的方法进行重写,提供自己的实现:

classAnimal{publicvoidspeak(){System.out.println("动物叫");}}classCatextendsAnimal{@Overridepublicvoidspeak(){System.out.println("喵喵喵");}}

4.2 重写的条件

条件要求
方法名必须相同
参数列表必须相同
返回值类型必须相同或者是其子类
访问权限不能低于父类(父类public,子类不能private)
异常不能抛出比父类更大的异常

4.3 @Override注解

推荐在重写的方法上加@Override注解:

  • 让编译器帮忙检查是否真的重写了
  • 提高代码可读性

4.4 重写 vs 重载

维度重写(Override)重载(Overload)
发生位置父子类之间同一个类中
方法名相同相同
参数列表必须相同必须不同
返回值相同或其子类无关
注解@Override

5. 继承中构造方法

5.1 父子类构造方法的执行顺序

子类构造方法默认第一行会调用父类的无参构造

classFather{publicFather(){System.out.println("父类构造方法");}}classSonextendsFather{publicSon(){super();// 默认就有,可以省略System.out.println("子类构造方法");}}// 创建对象Sons=newSon();// 输出:// 父类构造方法// 子类构造方法

5.2 父类没有无参构造怎么办?

如果父类只写了有参构造,没有无参构造,子类必须手动用super(参数)调用:

classFather{privateStringname;publicFather(Stringname){// 只有有参构造this.name=name;}}classSonextendsFather{publicSon(Stringname){super(name);// 必须手动调用父类的有参构造}}

5.3 super()的规则

规则说明
必须写在第一行super()必须是构造方法的第一条语句
和this()互斥一个构造方法不能同时调用super()this()
不写默认有如果不写,编译器会自动加super()

6. 多态

6.1 什么是多态?

同一种行为,不同对象表现出不同形态

比如“吃”这个行为:

  • 猫吃鱼
  • 狗吃肉
  • 人吃饭

6.2 多态的条件

条件说明
继承有父子类关系
重写子类重写了父类的方法
父类引用指向子类对象Father f = new Son();

6.3 多态的代码体现

classAnimal{publicvoideat(){System.out.println("动物吃东西");}}classCatextendsAnimal{@Overridepublicvoideat(){System.out.println("猫吃鱼");}}classDogextendsAnimal{@Overridepublicvoideat(){System.out.println("狗吃肉");}}publicclassTest{publicstaticvoidmain(String[]args){// 多态:父类引用指向子类对象Animala1=newCat();Animala2=newDog();a1.eat();// 猫吃鱼a2.eat();// 狗吃肉}}

6.4 多态的成员访问特点

成员类型访问特点
成员变量编译看左边,运行看左边(用父类的)
成员方法编译看左边,运行看右边(用子类的)
静态方法编译看左边,运行看左边(不算重写)
classFather{intnum=10;publicvoidshow(){System.out.println("Father show");}publicstaticvoidtest(){System.out.println("Father static");}}classSonextendsFather{intnum=20;@Overridepublicvoidshow(){System.out.println("Son show");}publicstaticvoidtest(){System.out.println("Son static");}}// 使用Fatherf=newSon();System.out.println(f.num);// 10(父类的变量)f.show();// Son show(子类的方法)f.test();// Father static(静态方法看左边)

7. 多态的优缺点

7.1 优点

解耦:方法参数写成父类类型,可以接收任何子类对象:

// 不用多态:每种动物都要写一个方法publicvoidfeedCat(Catcat){cat.eat();}publicvoidfeedDog(Dogdog){dog.eat();}publicvoidfeedPig(Pigpig){pig.eat();}// 用多态:一个方法搞定所有publicvoidfeed(Animalanimal){animal.eat();}

扩展性:新增动物类,不需要修改已有代码。

7.2 缺点

不能直接调用子类特有方法

Animala=newCat();a.eat();// 父类有,可以a.catchMouse();// 父类没有,不能调用

解决方法:向下转型

if(ainstanceofCat){Catc=(Cat)a;c.catchMouse();// 转成Cat后可以调用}

8. 向上转型和向下转型

8.1 向上转型(自动)

Catcat=newCat();Animalanimal=cat;// 向上转型,自动完成

特点:父类引用指向子类对象,但只能调用父类已有的方法。

8.2 向下转型(强制)

Animalanimal=newCat();Catcat=(Cat)animal;// 向下转型,需要强制转换

8.3 instanceof关键字

向下转型前,建议先用instanceof判断类型:

Animalanimal=newCat();if(animalinstanceofCat){Catcat=(Cat)animal;cat.catchMouse();}elseif(animalinstanceofDog){Dogdog=(Dog)animal;dog.watchHouse();}

Java 16+ 新写法

if(animalinstanceofCatcat){cat.catchMouse();// 自动转换,直接用}

9. 综合总结

9.1 继承总结

维度要点
格式class 子类 extends 父类
单继承一个子类只能有一个父类
成员变量就近原则,用super访问父类
成员方法可以重写,用@Override注解
构造方法先调用父类构造,再调子类

9.2 多态总结

维度要点
条件继承 + 重写 + 父类引用指向子类对象
变量编译运行都看左边(父类)
方法编译看左边,运行看右边(子类重写的)
静态编译运行都看左边
转型向上自动,向下强制(建议先instanceof)

9.3 对比表格

对比项继承多态
核心作用代码复用灵活扩展
关键词extends父类引用指向子类对象
方法调用调用哪个看对象类型编译看左,运行看右
典型场景抽取公共代码方法参数写成父类类型

10. 易错点总结

  1. 把重写写成重载:参数列表不同,导致不是重写而是新方法
  2. 子类构造方法忘记调用super:父类没有无参构造时必须手动调用
  3. this和super混淆:this访问当前类,super访问父类
  4. 向下转型不判断类型:可能导致ClassCastException
http://www.cnnetsun.cn/news/2006527.html

相关文章:

  • PyTorch 2.6镜像使用教程:手把手教你快速搭建GPU训练环境
  • 关于shell的简单用法
  • 绿激光3D打印散热器如何帮助机器人更加“从容冷静”的奔跑?
  • 用Gemini 3.1搞科研!你会发现这辈子有了
  • Phi-3.5-mini-instruct轻量推理优势:在低功耗GPU上实现<500ms首token延迟
  • 郭老师-人脉的本质:你强,世界才温柔
  • WooCommerce 多域名外链商品的动态联盟参数注入教程
  • 第8天 合并两个有序数组
  • 10年老兵带你学Java(第5课):接口与抽象类 - 抽象与契约
  • 类设计--友元+静态成员+对象之间的关系
  • 前端基础:form和input用法详解
  • Linux内核SCSI错误处理实战:当你的硬盘IO卡住或报错时,内核到底做了什么?
  • 万象视界灵坛实战教程:将语义解析结果接入Elasticsearch构建视觉搜索系统
  • Educational Codeforces Round 120 (Rated for Div. 2) vp补题
  • Phi-3.5-mini-instruct步骤详解:从model path配置到Gradio端口映射
  • 无人机送货时如何‘看’得更远?聊聊MPC里的预测时域K和采样时间dt怎么调
  • 别再被公式吓跑!用大白话和Python代码图解GAMP算法的核心思想
  • 别再对着屏幕列表发愁了!手把手教你根据手头的OLED屏型号,快速找到正确的U8g2构造器
  • 别再暴力搜索了!用‘可行性剪枝’5分钟搞定洛谷P1025数的划分
  • 智能车电磁循迹:从吴恩达的机器学习课到我的小车,聊聊归一化为什么比差比和更香
  • **WebAssembly实战进阶:用Rust构建高性能前端模块并集成到React应用中**在现代Web开发中,
  • 告别枯燥理论!用Proteus 8.15 + 51汇编亲手“点亮”硬件:数码管、按键、LED全搞定
  • 从电平转换到总线仲裁:UART、RS232与RS485的硬件差异如何重塑软件编程思维
  • Android13 Activity启动流程深度解析:从进程间通信到窗口树构建
  • 从电位器到内部温度传感器:一个STM32 ADC多通道采集的完整项目实战(含代码与波形分析)
  • 【效率革命】18款免费3dMAX插件与脚本,解锁你的创意生产力
  • 【Qwen3.5 系列技术解析】:2026 年原生多模态旗舰模型全景报告
  • 告别Command Not Found:手把手教你配置Mac上的zsh与Oh My Zsh(含Homebrew、zsh-autosuggestions插件安装)
  • 保姆级教程:在Ubuntu 20.04上搞定Velodyne VLP-16雷达的ROS驱动与Rviz可视化(含网络配置避坑)
  • 武汉大学计算机复试通关指南:从机考到面试的实战策略