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

【Java SE 】继承 与 多态 详解

 🔥博客主页🔥:【 坊钰_CSDN博客 】

欢迎各位点赞👍评论✍收藏⭐

目录

1. 继承

1.1 继承的原因

1.2 继承的概念

1.3 继承的语法

2. 子类访问父类

2.1 子类访问父类成员变量

2.1.1 子类与父类不存在同名成员变量

2.1.2 子类与父类存在同名成员变量

2.2   子类访问父类成员方法

2.2.1 子类和父类成员方法同名

3. super 关键字

3.1 子类的构造方法

3.2 super 和 this 的异同

3.3 代码的执行顺序

 4. 继承方式

4.1 final 关键字

4.1.1 final 修饰成员

4.1.2 final 修饰方法

4.1.3 final 修饰类

5. 多态

5.1 多态的概念

5.2 实现多态条件

5.3 向上转型和向下转型

5.3.1 向上转型

5.3.1.1  直接赋值

5.3.1.1  方法传参

5.3.1.1  方法返回

5.3.2 向下转型

5.4. 方法的重写

5.5 实现多态性

5.6 多态的优缺点

6. 小结


1. 继承

1.1 继承的原因

Java 是一种纯面向对象的编程语言,当我们用类来描述多个实体时,那么可能有几个类之间会存在一些关系,那么在设计时就需要考虑一下

比如:学生工人

我们用 Java 语言来描述

//学生类public class Student {String name;   //姓名int age;       //年龄float weight;  //体重public void sleep() {System.out.println("睡觉......");}//学生的工作public void study() {                 System.out.println("在教室学习......");}}//工人类public class Worker {String name;   //姓名int age;       //年龄float weight;  //体重public void sleep() {System.out.println("睡觉......");}//工人的工作public void work() {System.out.println("在工地工作......");}}

虽然,学生和工人的类定义出来了,但是他们类中有很多重复代码 

我们想一想,如果把这些相同的共性提取出来,就可以实现代码的复用 

1.2 继承的概念

一句话:继承是使代码具有复用性的手段,允许了在原有类的基础上进行扩展,添加新内容

继承好处:提取了共性,实现代码复用,那么我们可以在建一个类用来存放这些共性,就不必重复的写代码,只是需要时调用即可

1.3 继承的语法

Java 中用关键字 extends 来表示继承关系

修饰符 class 子类 extends 父类 {......
}

上述代码进行优化

//父类public class People {String name;   //姓名int age;       //年龄float weight;  //体重public void sleep() {System.out.println("睡觉......");}}//子类---学生public class Student extends People {  //继承public void study() {System.out.println("在教室学习......");}}//子类---工人public class Worker extends People  {  //继承public void work() {System.out.println("在工地工作......");}}
  •  子类会将父类中成员变量和方法都继承到子类中
  • 继承后,子类必须有新的变量或方法,否则就没有继承的必要了

2. 子类访问父类

在继承好了之后,子类就可以访问父类各种成员了

2.1 子类访问父类成员变量

2.1.1 子类与父类不存在同名成员变量

//父类public class TestClassFather {int a;    //父类变量int b;}//子类public class Son extends TestClassFather {int c;   //子类变量public void Fun() {    //直接使用即可a = 100;b = 200;c = 300;}}

2.1.2 子类与父类存在同名成员变量

//父类public class TestClassFather {//父类变量  int a;   int b;}//子类public class Son extends TestClassFather {//子类变量int b;    //与子类相同int c;   public void Fun() {    //直接使用即可a = 100;b = 200;   //优先访问自己的变量c = 300;}}

注意事项

  • 子类与父类存在同名成员变量时,优先访问自己的
  • 访问的成员,子类没有,那就访问父类的,如果都没有,则报错

2.2   子类访问父类成员方法

//父类public class TestClassFather {int a;int b;public void Fun() {System.out.println("哈哈");}}//子类public class Son extends TestClassFather {int c;public void method() {Fun();   //直接访问即可}}

2.2.1 子类和父类成员方法同名

//父类public class TestClassFather {int a;int b;public void Fun() {System.out.println("哈哈");}public void Fun(int a) {System.out.println("哈哈");}}//子类class Son extends TestClassFather {int c;public void Fun() {System.out.println("呵呵");}public void method() {Fun();     //访问子类Fun(10); //访问父类}}
  • 同名时,优先在子类中寻找,子类没有,在去父类中寻找
  • 也可根据方法的参数进行寻找,如果都没有,则报错

3. super 关键字

在编程中,可能会遇到,当子类和父类的成员变量或方法同名时,又想访问父类成员,该怎么做呢?这时,Java 提供了 super 关键字,用来在子类中访问父类的成员

//父类public class TestClassFather {int a =  10;public void Fun() {System.out.println("父类:Fun()");}}//子类class Son extends TestClassFather {int a = 20;public void Fun() {System.out.println("子类:Fun()");}public void pirnt() {System.out.println(a);           //子类System.out.println(super.a);     //父类Fun();                           //子类super.Fun();                     //父类}}

运行结果:

这就是 super 的用法

3.1 子类的构造方法

俗话说,父子父子,先有父,在有子

在执行子类构造方法时,需要先执行父类的构造方法,然后在执行子类的构造方法

public class A {public A() {System.out.println("父类构造方法......");}
}class B extends A {public B() {System.out.println("子类构造方法......");}public static void main(String[] args) {B b = new B();           }
}

运行结果:

  • 若父类中无构造方法,编译器会自动添加一个无参构造方法,若果有,则不加
  • 若父类定义无参或默认的构造方法,在子类构造方法中第一行,编译器会默认调用 super() 
  • 若父类定义有参数的构造方法,则要为子类也要显示定义构造方法,否则失败
  • super 调用父类时,必须在第一行,否则报错
  • super 只能在子类中出现一次,不能和 this 同时出现

3.2 super 和 this 的异同

 学了 super 和 this 关键字,那他们有什么区别呢?

相同点

  • 都是 Java 的关键字
  • 都不能在静态方法中使用
  • 在构造方法中使用时,都只能在第一行,且不能同时存在

不同点

  • this 用于本类中的方法和属性的引用,而 super 用于访问父类继承下来的方法和属性、
  • 调用构造方法时,this 用于调用本类的构造方法,super 用于调用父类的构造方法
  • 构造方法中一定会存在 super 的调用,不写编译器自动调用,this 不写就没有

 3.3 代码的执行顺序

先看下面代码,思考一下运行结果是什么?为什么?

public class A {static {System.out.println("父类静态代码块......");}{System.out.println("父类实例代码块......");}public A() {System.out.println("父类构造方法......");}
}class B extends A {static {System.out.println("子类静态代码块......");}{System.out.println("子类实例代码块......");}public B() {System.out.println("子类构造方法......");}public static void main(String[] args) {B b = new B();System.out.println("===========");B b1 = new B();}
}

运行结果

通过结果分析,总结顺序规律:

  • 父类的静态代码块优先于子类的静态代码块
  • 父类的实例代码块和构造代码块接着执行
  • 子类的实例代码块和构造代码块接着执行
  • 第二次在实例化时,父类和子类的静态代码块不在运行,他们只执行一次

 4. 继承方式

Java 中的类只能单继承,不支持多继承,如果想从语法上限制继承,我们可以用 final 关键字来修饰

4.1 final 关键字

final 可以修饰 成员、类、方法

4.1.1 final 修饰成员

被 final 修饰的成员,成员的值不可以被修改

final int a = 10; //不可以被修改

4.1.2 final 修饰方法

被 final 修饰的方法,方法不可以被重写

public final void study() {  //不可以被重写System.out.println("在教室学习......");
}

4.1.3 final 修饰类

被 final 修饰的类,类不可以继承

public  final class A {......
}

5. 多态

5.1 多态的概念

多态就是多种形态,对于某个行为,不同对象去完成会产生不同的状态

一句话:同一种方法,不同对象对应的结果不同

5.2 实现多态条件

  • 必须在继承条件下进行
  • 存在子类向父类的向上转型
  • 子类必须要对父类的方法进行重写
  • 通过父类调用重写的方法

5.3 向上转型和向下转型

5.3.1 向上转型

子类对象当作父类对象使用

语法格式

父类类型 对象名 = new 子类类型( );

People people = new Student();   //子类对象当作父类对象 

向上转型时通常有三种情况

5.3.1.1  直接赋值
People people = new Student();   //直接赋值
5.3.1.1  方法传参
public class Test {public static void Fun(People people) {  //发生了向上转型people.work();}public static void main(String[] args) {Student student = new Student();Fun(student );   //方法传参时出现了向上转型}
}
5.3.1.1  方法返回
//方法返回时发生了向上转型public static People Fun(Student student) {  return student;
}

5.3.2 向下转型

向下转型和向上转型相反,父类对象强转为子类对象使用

语法格式

子类类型 对象名 =(子类类型) new 父类类型( );

//强制类型转换Student student = (Student) new people();

该转型用的较少,且不安全

5.4. 方法的重写

重写:也称为覆盖,是子类对于父类的方法进行重写编写,返回值、形参都不能改变

//父类public class People {String name;int age;float weight;public People(String name, int age) {this.name = name;this.age = age;}public void work() {System.out.println(name+" 在工作......");}}//子类public class Worker extends People  {public Worker(String name, int age) {super(name, age);}//对父类中的方法进行了重写public void work() {  System.out.println(name+" 在工地工作......");}}

重写的规则

  • 子类重写父类方法时,返回值和形参必须都一致
  • 重写的方法的返回值可以不同,但前提必须有父子关系
  • 子类方法的访问限制符的范围必须大于等于父类的访问限制符
  • 父类方法被 static 或 private 修饰,则不能重写

前面学习了重载,那他们俩区别是?

5.5 实现多态性

//父类public class People {String name;int age;float weight;public People(String name, int age) {this.name = name;this.age = age;}public void work() {System.out.println(name+" 在工作......");}}//子类---学生public class Student extends People  {public Student(String name, int age) {super(name, age);}//对父类重写public void work() {System.out.println(name+" 在教室学习......");}}//子类---工人public class Worker extends People  {public Worker(String name, int age) {super(name, age);}//对父类重写public void work() {System.out.println(name+" 在工地工作......");}}//多态性的实现public class Test {public static void Fun(People people) {    //传参进行向上转型people.work();}public static void main(String[] args) {People people1 = new Student("张三",20);People people2 = new Worker("工人",30);Fun(people1);Fun(people2);}
}

这就是多态性,对于同一个方法 Fun ( ) ,当我们传入不同对象时,它处理的结果不同,多态性级体现出来了

5.6 多态的优缺点

优点

  • 降低了代码的圈复杂度,避免了大量的 if-else
  • 使代码的可扩展性增强

缺点

  • 代码运行效率降低 

6. 小结

以上就是对继承和多态的了解,具体还需宝子们去实践,如果觉得该博客对你有用的话,希望一键三连,点个关注不迷路,谢谢支持 ! 


http://www.mrgr.cn/news/54987.html

相关文章:

  • 使用休眠的方式来解决电脑合盖后偶尔不能正常睡眠的问题
  • React是如何工作的?
  • WebSocket状态码及异常报错1006
  • WebSocket Secure (WSS)
  • 开启RefCell debug_refcell feature查看借用冲突位置
  • 企业博客SEO优化:8个必备工具与资源指南
  • 1. DLT645协议解析
  • 看电视直播神器,家中老人乐开怀
  • 新程序员必备的5个VS Code插件
  • IO进程---day5
  • React04 - react ajax、axios、路由和antd UI
  • 深度学习 之 模型部署 使用Flask和PyTorch构建图像分类Web服务
  • DreamFace 4.7.1 | 图片说话,数字人
  • 计算机网络408真题解析(湖科大教书匠)
  • STM32调试,发现HAL_Init();之后无法调试,甚至无法让程序停下来
  • 详解equals底层原理
  • 滑动窗口,水果成篮 , 找到字符串中所有字母异位词 ,串联所有单词的子串
  • 练习题 - Scrapy爬虫框架 Selectors 数据选择器
  • 权限管理系统的详细解析与实现
  • 栈与队列的常见接口的实现
  • yolov8实例分隔
  • OpenCV图像处理——查找线条的转折点
  • 鸿蒙中富文本编辑与展示
  • Guava防击穿回源-同步防击穿
  • 数据结构7——二叉树的顺序结构以及堆的实现
  • jupyter notebook中执行过程中更新模块代码,再执行没有更新执行