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

news2024/11/16 6:40:19

目录

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.coloradmin.cn/o/1078403.html

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

相关文章

企业安全生产隐患排查治理系统

安全生产隐患排查治理系统,实现对重大危险源企业、安全隐患信息的登记、审查、评估、分类、统计、分析和处理。系统涵盖了安全隐患排查整治工作的各项基本内容,能对隐患排查整治信息及时、有效地进行跟踪、整改,并将统计数据及时上报&#xf…

一键报警全网通4G可视对讲终端4G 有线双网络可视对讲终端

一键报警全网通4G可视对讲终端 4G 有线双网络可视对讲终端 产品简介: 一键求助对讲广播终端是用于平安城市、公交车站,公交车,高速收费站,景区,公园,工厂,养老院,银行、医院、学校…

腾讯云我的世界mc服务器配置选择(价格值得)

腾讯云服务器开Minecraft我的世界服务器配置怎么选择?10人以内玩2核4G就够用了,腾讯云开我的世界服务器选择轻量应用服务器就够了,轻量CPU采用至强白金处理器,大型整合包一般1.12版本的,轻量2核4G配置都差不多的&#…

面试必考精华版Leetcode547. 省份数量

题目&#xff1a; 代码&#xff08;首刷看解析&#xff09;&#xff1a; class Solution { public:void dfs(vector<vector<int>>& isConnected,vector<int>& isVis,int i){int n isConnected.size();for(int j0;j<n;j){if(isConnected[i][j]1 …

深度学习基础知识 学习率调度器的用法解析

深度学习基础知识 学习率调度器的用法解析 1、自定义学习率调度器**&#xff1a;**torch.optim.lr_scheduler.LambdaLR2、正儿八经的模型搭建流程以及学习率调度器的使用设置 1、自定义学习率调度器**&#xff1a;**torch.optim.lr_scheduler.LambdaLR 实验代码&#xff1a; i…

安装Docker(Linux:CentOS)

大家好我是苏麟今安装一下Docker. 安装Docker Docker 分为 CE 和 EE 两大版本。CE 即社区版&#xff08;免费&#xff0c;支持周期 7 个月&#xff09;&#xff0c;EE 即企业版&#xff0c;强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月。 Docker CE 分为 stab…

抖音seo源码矩阵系统--源码源头技术开发

抖音SEO源码矩阵系统是一款基于源码源头技术开发的全新系统。它通过优化抖音的搜索引擎优化(SEO)机制&#xff0c;帮助用户提升抖音视频的曝光量和搜索排名&#xff0c;从而增加视频的流量和观众数量。系统提供了一系列强大的功能&#xff0c;包括关键词研究、标题优化、标签管…

PlantUML 绘图

官网 https://plantuml.com/zh/ 示例 绘制时序图 USB 枚举过程 PlantUML 源码 startuml host <-- device : device insert host note right : step 1 host -> device : get speed, reset, speed check note right : step 2 host -> device …

Android性能优化,有关内存抖动与解决方案

一、内存抖动 1.内存抖动的危害 由于垃圾回收机制老年代里面的标记清理算法&#xff0c;大有大量对象创建并快速销毁后&#xff0c;会在内存里面留下大量的内存碎片&#xff0c;这时如果有大对象需要申请内存时&#xff0c;就会产生OOM。 2.如何查看程序是否有内存抖动现象 …

小白网络安全学习手册—黑客

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟…

安防视频监控平台EasyCVR出现“no space left on device磁盘空间不足”是什么原因?该如何解决?

视频监控TSINGSEE青犀视频平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;在视频监控播放上&#xff0c;TSINGSEE青犀视频安防监控汇聚平台可支持1、4、9、16个画面窗口播放&#xff0c;可同时播放多路视频流&#…

BM74 数字字符串转化成IP地址

数字字符串转化成IP地址_牛客题霸_牛客网现在有一个只包含数字的字符串&#xff0c;将该字符串转化成IP地址的形式&#xff0c;返回所有可能的情况。。题目来自【牛客题霸】https://www.nowcoder.com/practice/ce73540d47374dbe85b3125f57727e1e?tpId295&tags&title&a…

Vue思考题_01v-for与v-if的优先级谁更高

目录 vue2vue3 官方文档上说不推荐将v-for与v-if在同一个标签上使用&#xff0c;因为两者优先级并不明显。 那么到底是那个指令的优先级比较高呢&#xff1f; 在vue2与vue3中答案是相反的。 vue2 在vue2中将2个指令放在同一个标签上 <template><ul><li v-fo…

2023-10-10-C++指针和引用【程序员生涯的第一座里程碑】

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f4a5;&#x1f4a5;&#x1f4a5;欢迎来到&#x1f91e;汤姆&#x1f91e;的csdn博文&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f49f;&#x1f49f;喜欢的朋友可以关注一下&#xf…

中职院校网络综合布线技术理实一体化实训室建设方案

中职院校的网络综合布线技术课程存在一些问题,主要表现在: 教师过于注重理论知识的讲授,实践教学被忽视。学校硬件设施不足,无法开展案例中的实际操作,影响学生实践能力的培养。学生进入工作后,实际操作能力较差,难以胜任工作岗位。 为了提高学生的网络综合布线技能和操作能力…

碰撞检测算法——分离轴算法实现(一)

在实现分离轴算法前&#xff0c;需要做一些准备工作&#xff0c;在Unity中实现自定义多边形的显示&#xff0c;以及获取多边形的顶点和边的数据。 1.实现自定义多边形显示 Unity中MeshFilter是负责处理Mesh&#xff08;网格&#xff09;的信息的引用&#xff0c;MeshRender是渲…

管程的定义以及基本特征

1.引入管程 为了解决信号量机制存在的问题&#xff1a;编写程序困难、易出错。 1973年&#xff0c;Brinch Hansen首次在程序设计语言(Pascal)中引入了“管程”成分&#xff1a;一种高级同步机制。 2.管程的定义和基本特征 1.管程是一种特殊的软件模块&#xff0c;有这些部分…

Leetcode——数组的遍历系列练习

485. 最大连续 1 的个数 class Solution { public:int findMaxConsecutiveOnes(vector<int>& nums) {// 记录最大连续1个数int max 0;// 记录数组中存在1个数int sum 0;// 遍历连续1个数int count 0;for (int i 0; i < nums.size() - 1; i) {if (nums[i] 1)s…

linux | linux扩大磁盘空间 | centos7.9 | 虚拟机

注意&#xff1a;可以完全参考下面这边博客&#xff08;我只是搬运工&#xff09; centos扩大磁盘空间 简单讲讲&#xff0c;为什么有点失落落的&#xff1f; 明明就是一个 很程序化的东西 可是网上一大推 天花乱坠 而且很多人都是半吊子水&#xff0c;甚至半吊子都没有 通过关…

jdbc(DriverManager+Connection+Statement+ResultSet)+SQL注入+开启预编译+数据连接池

1 JDBC概念 JDBC 就是使用Java连接并操作数据库的一套API 全称&#xff1a;( Java DataBase Connectivity ) Java 数据库连接 2 JDBC优势 可随时替换底层数据库&#xff0c;访问数据库的Java代码基本不变 以后编写操作数据库的代码只需要面向JDBC&#xff08;接口&#xf…