你真的懂Java的继承吗?你知道什么时候用继承吗?设计继承是为了什么?

目录

1. 封装的意义是什么?

2. 为什么需要继承?

3. 继承是什么?如何使用?

4. 继承的好处是什么?

5. 设计继承需要注意什么?

6. 继承的特点

7. 子类到底继承了父类的哪些内容

7.1 继承内容

7.2 虚方法表的概念

8. 继承中成员变量的访问特点

8.1 例子1:方法优先访问局部变量

8.2 例子2:方法其次访问成员变量

8.3 例子3:方法最后访问父类变量

8.4 例子4:this 主动调用成员变量,super 主动调用父类变量

8.5 总结

9. 继承中方法的重写详情

9.1 重写的目的与注意事项

9.2 虚方法表再重写中的作用

10.  继承中构造方法的访问特点


1. 封装的意义是什么?

封装想必大家都不陌生,众所周知,Java最重要的一个特点就是面向对象,对象代表什么,就要封装什么样的数据,并提供数据对应的内容。

我们可以利用封装将以前的一些零散的属性信息,方法封装在一起,组成一个整体,这个整体就是我们常说的对象。在没有封装以前,我们就需要对这个零三的属性和方法分别做处理,将它们作为参数传入到方法中,有了封装之后,我们只需要一个对象传入方法中,就可以解决以前的所有烦恼,非常的方便。

举个最简单的例子,现在有一个打印学生信息的类,类中有一些属性和方法

现在有一业务需求,要求打印学生的相关信息。

(1)没有封装加入:我们就需要把学生的信息全部作为参数传递到方法中,有多少个属性就要传递多少个参数;

(2)有了封装的加入:我们将学生的信息封装到学生对象中,将get和set方法也封装到学生对象中,然后将对象作为参数传递到方法中,这样当我们需要打印学生信息时,只需要通过对象的 get 方法获取到属性信息即可,非常的方便,加大的简化的业务的复杂度。

2. 为什么需要继承?

我来说明一个场景引出一个问题,你们或许就会明白了。

假设现在的业务中,我有两个类,一个是学生类 Student,一个是老师类 Teacher。它们的属性和方法如下图所示,已经封装完成

仔细观察上面两个类,有没有发现什么问题。其实很显然,这两个类重复的代码太多了,那么有没有什么办法能够解决这个问题呢?我们可把可以吧重复的代码抽取出来重复使用呢?就像封装一样。

那么接下来就需要用到今天的重点——继承。

3. 继承是什么?如何使用?

在实际开发过程中,无法避免的会产生一些重复相似的属性和方法,为了避免让我们项目代码过于荣誉和臃肿,就引入了继承这么一个概念。

Java 中关于继承提供了一个关键字 extend,我们使用这个关键字,就可以让一个类与另一个类之间产生继承关系,使用方法也比较简单,只需要在一个类的后面写上 "extend 被继承类类名"。

使用继承,我们就可以对上面的 Student 类和 Teacher 类进行优化,将两个类的公共部分抽取出来,生成第三个类,让 Student 类和 Teacher 类都继承这第三个类。

如下图所示,Student 类和 Teacher 类都被称为子类(也叫派生类),Person 类被称为父类(也可以叫超类或基类)。

4. 继承的好处是什么?

(1)通过继承,我们可以将一些类中相同的属性和方法,即重复的代码抽取到一个类中作为父类,提高了代码的复用性,降低的代码的冗余。

(2)青出于蓝而胜于蓝。子类在继承了父类之后,得到了父类中的所有属性和方法(私有属性和方法除外),还可以在自己的类中添加额外的属性和方法,扩展自己的功能,让子类更加强大,以便于满足更多更复杂的业务需求。

5. 设计继承需要注意什么?

请同学们牢牢记住下面这句话,"当类与类之间,存在相同(共性)的内容,并且满足子类是父类中的一种,就可以考虑使用继承优化代码"

即使用继承要满足两点:(1)存在相同内容;(2)一定一定要满足子类是父类中的一种,这一点不能忽视!!!

Student 类和 Teacher 类都是人的一种,所以他们都可以继承 Person 类;

Manager 管理者类和 Coder 程序猿类都是员工的一种,他们可以同时继承 Employee 类;

而大家看下面这种情况,我能否让 Coder 程序猿类和 Phone 手机类继承一个 Goods 商品类呢?它们都有相同的属性 id 和名字属性。

答案是不能的,如果你在项目开发中这样做了,那就等着被项目组长教训吧。

所以在强调一遍,使用继承时一定要满足两点。

第一点:类与类之间有共同的内容;

第二点:子类必须是父类中的一种,如果不是一种就算有相同的属性也不能使用继承;

6. 继承的特点

集成的特点,只需要记住一句话,"Java只支持单继承,不支持多继承,但支持多层继承"。

我们拆分成三句话来说明。

Java 只支持单继承:在 Java 中,一个类只能继承一个类,不能在继承其他的类;可以理解为一个儿子只能有一个父亲,不能有两个。

Java 不支持多继承:假设我现在的 A类 继承了 B类,而且B类中有一个方法 method 打印一句话"我继承了B类",A类 也继承了 C类,C类中也有一个方法 method 打印一句话 "我继承了C类",那么当A类的对象调用 method 方法时,它就蒙了,他不知道该调用哪个,所以为了避免这种情况的发生,Java 中不支持多继承。

Java 支持多层继承:这个意思就是A类继承了B类,B类也可以继承C类,C类也可以继承D类,类似于套娃,无限循环。就好比是四世同堂,儿子——>爸爸——>爷爷——>姥爷。

还有一点需要注意,Java 中的所有类都直接或者间接的继承了 Object 类。

7. 子类到底继承了父类的哪些内容

7.1 继承内容

在一个类中,我们通常会定义构造方法,成员变量,成员方法。

子类继承父类时,它所能继承的内容如下图所示

(1)父类中的构造方法,不管是不是私有的,子类都继承不了;

(2)父类中的成员变量,不管是不是私有的,子类都能继承,只是父类中的成员变量被锁定了,子类可以继承,但是子类访问不了;

(3)父类中的成员变量,非私有的方法可以继承下来;

7.2 虚方法表的概念

在成员方法的继承中,我要补充一个额外的点,子类在继承父类中的成员方法时,实际上会继承父类的虚方法表

这里给大家解释一下,Java 在最顶级的父类开始,会设立一个虚方法表,它会把这个类当中经常可能会用到的方法单独的抽取出来,放到虚方法表中。

Java 是如何判断一个方法会经常被使用呢?方法需要满足以下三点:

(1)不被 private 修饰;

(2)不被 static 修饰;

(3)不被 final 修饰;

满足这三点的方法,就会被存放到虚方法表中。

在继承的过程中,父类就会把这个需方发表交给子类,子类在父类虚方法表的基础上,添加自己的虚方法,然后继续交给后续的子类,层层传递,如下图所示。

8. 继承中成员变量的访问特点

在继承中,成员变量的访问特点遵循 "就近原则,谁离我近,我就用谁"。

8.1 例子1:方法优先访问局部变量

如下代码

public class Test9 {// 定义 main 方法做测试public static void main(String[] args) {// 定义 Son 类对象Son son = new Son();// 调用方法son.ziShow();}
}
// 定义一个父类
class Futher{// 定义一个字符串String name = "父类字符串";
}
// 定义一个儿子类继承父类
class Son extends Futher{// 定义一个字符串String name = "子类字符串";// 定义一个方法public void ziShow(){String name = "方法内部的字符串";System.out.println(name);}
}

运行上述代码,就可以在控制台看到,打印出的是方法内部的 name 字符串,因为方法内部的字符串距离方法最近

8.2 例子2:方法其次访问成员变量

刚才的演示中,方法内部本身就有 name 字符串,那么现在我将方法内部的字符串删除,再重新运行,就可以在控制台中看到如下结果,

所以可以得出结论,当继承中方法访问的变量在方法内部存在时,会优先就近访问方法内部的局部变量;当方法内部没有变量可以访问时,会去访问类中的成员变量。 

8.3 例子3:方法最后访问父类变量

我们对上面的方法再做修改,将方法类中的成员变量 name 也删除,再次运行,得出如下结果

结合上面三个例子:可以得出结论,当方法内部没有变量可以访问时,方法会先去访问了当前类的成员变量,如果当前方法类的成员变量也没有可以访问时,会最后去访问父类中的成员变量。 

8.4 例子4:this 主动调用成员变量,super 主动调用父类变量

当我们不想访问方法内部的变量时,就可以通过 this 关键字主动调用方法的成员变量,或通过 super 关键字调用父类变量,在原本的代码基础上稍微做修改;

如下所示

8.5 总结

OK,下面我们几句句话来总结上面四个例子得出的结论。

(1)在继承中,方法调用变量时会采用就近原则,当方法想要访问的变量方法内部本身就有时,会最优先访问方法内部的局部变量;

(2)当方法内部访问不到变量时,会去方法当前类成员变量中寻找访问;

(3)如果成员变量中也访问不到时,会最后去父类成员变量访问;

(4)如果想要主动访问当前方法类成员变量,可以通过 this 关键字,如果想要调用父类成员变量,则可以通过 super 关键字。

9. 继承中方法的重写详情

9.1 重写的目的与注意事项

子类在继承了父类的方法之后,可以使用父类中的方法,但是在实际开发过程中,子类继承父类之后,通常会扩展自己额外的功能,那么此时从父类继承下来的方法可能就满足不了业务需求了,这个时候就需要用到方法的重写,我们可以在子类冲重新编写重复类那里继承下来的方法的执行逻辑,高造成满足我们业务需求的方法。

再进行重写时,需要满足以下几点需求。

(1)重写方法的名称,形参列表必须与父类保持一致;

(2)重写的方法上方要加上 @Override 注解;

(3)子类在重写父类方法时,方法的访问权限必须大于等与父类,方法的返回值范围必须小于等于父类;

(4)父类中的私有方法不能被重写;

(5)父类中的静态方法,即被 static 修饰的方法不能被重写,重写会报错;

9.2 虚方法表再重写中的作用

回顾我们上面提到的虚方法表,父类会把常用的方法存放到虚方法表中交给子类,其实在子类重写父类方法的过程中,其实重写的就是虚方法表中从父类那里得到的方法。

如下图所示,如果B类中重写了从父类C那里继承过来的 method2 方法,那么被重写后的 method2 方法就会被加入到虚方法表中,此时A类从B类那里继承过来的 method2 方法,实际上并不是最原始的C类中的方法,而是已经被B类重写后的 method2 方法。

10.  继承中构造方法的访问特点

(1)在继承体系中,子类不能继承父类的构造方法,但是可以通过 super 调用;

(2)子类在执行构造方法之前,会先去执行父类的无参构造;

我们用一段代码来证明一下

public class Test9 {// 定义 main 方法做测试public static void main(String[] args) {// 无参定义 Son 类对象Son son = new Son();// 带参定义 Son 类对象Son son2 = new Son("张三");}
}
// 定义一个父类
class Futher{String name;public Futher(){System.out.println("父类无参构造方法先执行");}public Futher(String name) {System.out.println("父类带参构造");this.name = name;}
}
// 定义一个儿子类继承父类
class Son extends Futher{String name;public Son(){System.out.println("无参构造创建 Son 对象");}public Son(String name) {System.out.println("带参构造创建 Son 对象");this.name = name;}
}

运行得出如下结果

从运行结果我们可以看出,创建子类时不管我们使用无参构造还是带参构造,父类的无参构造方法都会执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/100569.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【WSN】模拟无线传感器网络研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

html 笔记:CSS

1 什么是CSS CSS 指层叠样式表 (Cascading Style Sheets) 样式定义如何显示 HTML 元素样式通常存储在样式表中 1.1 css的语法格式 1.1.1 选择器种类 HTML选择器: 重新定义HTML的某种标签的显示格式id选择器 对于HTML文档中的某个标签,定义它的显示格式…

JavaScript进阶(二十三):立即执行函数(匿名函数)( ( ) { } ( ) )含义解析

文章目录 一、前言二、立即执行函数2.1 立即执行函数使用的场景 三、拓展阅读 一、前言 前端项目改造过程中,引入的工具类实现如下: var tensquared(function(x) {return x*x; }(10)); 拆解以上语句如下: var tensquared xx; 这是赋值语句…

HTML5+CSS3+移动web 前端开发入门笔记(二)HTML标签详解

HTML标签&#xff1a;排版标签 排版标签用于对网页内容进行布局和样式的调整。下面是对常见排版标签的详细介绍&#xff1a; <h1>: 定义一级标题&#xff0c;通常用于标题栏或页面主要内容的标题。<p>: 定义段落&#xff0c;用于将文字分段展示&#xff0c;段落之…

Jmeter 链接MySQL测试

1.环境部署 1.1官网下载MySQL Connector https://dev.mysql.com/downloads/connector/j/ 1.2 解压后&#xff0c;将jar放到jmeter/lib目录下 1.3 在测试计划中添加引用 2.脚本设置 2.1设置JDBC Connection Configuration 先添加一个setUp线程中&#xff0c;在setUp中添加“…

2023年台州市第三届网络安全技能大赛(MISC)—Black Mamba

前言&#xff1a;当时比赛没有做出来现在来复现一下 就当记录一下&#xff08;这个思路没想到&#xff09; Black Mamba&#xff1a; 一张图片 常规得分离&#xff0c;属性&#xff0c;LSB&#xff0c;盲水印等都尝试过 无果&#xff01; 考点&#xff1a;异或解密&#xff0…

计算机算法分析与设计(8)---图像压缩动态规划算法(含C++代码)

文章目录 一、知识概述1.1 问题描述1.2 算法思想1.3 算法设计1.4 例题分析 二、代码 一、知识概述 1.1 问题描述 1. 一幅图像的由很多个像素点构成&#xff0c;像素点越多分辨率越高&#xff0c;像素的灰度值范围为0~255&#xff0c;也就是需要8bit来存储一个像素的灰度值信息…

【每日一练】勾股定理困难版

目录 题目官方给的解题思路源代码附最大公因数辗转相除法更相减损术 所有因数参考文献 题目 给定斜边z的值&#xff0c;求所有直角边x和y的组合数&#xff08;x、y和z都是正整数&#xff09;。 仅有一行输入&#xff0c;即斜边z的值&#xff08;z是正整数&#xff0c;且z<1…

nginx配置实例-负载均衡

1 实现效果&#xff1a; 浏览器访问nginx&#xff0c;输入访问nginx地址&#xff0c;然后负载均衡到tomcat8080和8002端口中 2 准备工作&#xff1a; 1&#xff09;准备两台tomcat容器&#xff0c;一台8080&#xff0c;一台8081 2&#xff09;在两台tomcat里面的webapps目录…

提升企业管理效率!金蝶软件配置自定义域名,快速实现公网远程访问

文章目录 前言1. 保留自定义域名2. 域名解析3. 配置自定义域名4. 关于服务器选择以及域名备案的说明4.1 关于服务器地区的选择&#xff1a;4.2 关于自定义域名备案&#xff1a;4.3 关于域名过白名单&#xff1a; 前言 上篇文章我们讲过如何安装金蝶云星空&#xff0c;实现异地…

云计算引领数字化时代

一、云计算的定义和演进 云计算是一种通过互联网将计算资源&#xff08;例如存储、处理能力和软件等&#xff09;提供给用户的方式。这种分布式的计算模式&#xff0c;使得用户无需购买昂贵的硬件设备&#xff0c;也不需要关注底层的技术细节&#xff0c;只需通过互联网就能获…

wpf webBrowser控件 常用的函数和内存泄漏问题

介绍 WebBrowsers可以让我们在窗体中进行导航网页。 WebBrowser控件内部使用ie的引擎&#xff0c;因此使用WebBrowser我们必须安装ie浏览器&#xff08;windows默认安装的&#xff09;。 使用 直接在xmal中使用webBrowser控件 <WebBrowser x:Name"WebBrowser1"…

【C++】List -- 详解

一、list的介绍及使用 https://cplusplus.com/reference/list/list/?kwlist list 是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。 list 的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&…

PCA和SVD数据降维

PCA&#xff08;Principal Component Analysis&#xff09; 是一种常见的数据分析方式&#xff0c;常用于高维数据的降维&#xff0c;可用于提取数据的主要特征分量。 最大可分性 基向量乘原始矩阵会将矩阵映射到这个基向量空间中&#xff0c;如果基的数量少于向量本身的维数…

数据产品读书笔记——认识数据产品经理

&#x1f33b;大家可能听说的更多是产品经理这个角色&#xff0c;对数据产品经理可能或多或少了解一些&#xff0c;但又不能准确的描述数据产品经理的主要职能和与其他产品的不同&#xff0c;因此通过读一些书来对数据产品经理有一个准确且全面的认知。 目录 1. 数据的产品分类…

安卓 kotlin-supportFragmentManager报红

如果你继承baseActivity 请查看 是不是继承 AppCompatActivity

sface人脸相似度检测

sface人脸相似度检测&#xff0c;基于OPENCV&#xff0c;人脸检测采用yunet&#xff0c;人脸识别采用sface&#xff0c;支持PYTHON/C开发&#xff0c;图片来自网络&#xff0c;侵权请联系本人立即删除 yunet人脸检测sface人脸识别&#xff0c;检测两张图片的人脸相似度

Spring Security 6.1.x 系列 (1)—— 初识Spring Security

一、 Spring Security 概述 Spring Security是Spring组织提供的一个开源安全框架&#xff0c;基于Spring开发&#xff0c;所以非常适合在Spring Boot中使用。 官方文档地址&#xff1a;https://docs.spring.io/spring-security/reference/index.html GitHub地址&#xff1a;…

智能视频监控,究竟“智”在哪里?

当人们一提到智能视频监控时&#xff0c;就会想起高清摄像头、人脸识别等技术。其实不然&#xff0c;真正智能视频监控不仅仅是这些技术算法&#xff0c;更重要的是如何将这些算法融入到应用场景中&#xff0c;更好地去服务大众、起到降本增效的作用。 首先&#xff0c;智能视…

数据结构和算法(10):B-树

B-树&#xff1a;大数据 现代电子计算机发展速度空前&#xff0c;就存储能力而言&#xff0c;情况似乎也是如此&#xff1a;如今容量以TB计的硬盘也不过数百元&#xff0c;内存的常规容量也已达到GB量级。 然而从实际应用的需求来看&#xff0c;问题规模的膨胀却远远快于存储能…