【剧前爆米花--爪哇岛寻宝】面向对象的三大特性——封装、继承以及多态的详细剖析(上——继承)。

news2025/2/25 18:08:21

作者:困了电视剧

专栏:《JavaSE语法与底层详解》

文章分布:这是一篇关于Java面向对象三大特性——继承的文章,在本篇文章中我会分享继承的一些基础语法以及类在继承时代码的底层逻辑和执行顺序。

 

目录

继承

需求

继承的定义及语法格式

子类中访问父类成员

super关键字

子类构造方法

子类的初始化过程——代码的执行顺序

类从加载到实例化的大体流程

举个栗子


 

继承

Java使用类这一引用类型对现实中的实体进行描述,通过类中的成员描述一个事物的属性,通过实例化对象来进行相关的操作,但是世界上的事物错综复杂,事物与事物之间很大可能会存在关联,在程序设计的时候就需要考虑。

需求

我们举一个日常生活中的栗子:人们在日常生活中可能会养一只猫或者是养一条狗,现在我需要用Java对他们进行描述:

class Cat{
    String name;
    String sex;
    int age;
    public void sleep(){}
    public void eat(){
        System.out.println("吃猫粮");
    }
    public void speak(){
        System.out.println("喵");
    }
}

class Dog{
    String name;
    String sex;
    int age;
    public void sleep(){}
    public void eat(){
        System.out.println("吃狗粮");
    }
    public void speak(){
        System.out.println("汪");
    }
}

对于上述代码,我们可以清晰地看到,他们虽然是两个不同的事物,但是他们的属性相同,行为也有相同的地方,那我们定义两个类是不是就造成了代码的冗长,增加了出错的可能?

为了解决这一问题Java 的研发团队引入了继承这一概念,专门用来进行共性抽取,实现代码复用。 

继承的定义及语法格式

继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性 的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了 由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。

为了表示继承关系,Java中用extends关键字来表示类与类之间的继承。比如在上述栗子中,由于猫和狗都是动物,所以我可以写个动物类 ,让猫和狗都对其进行继承:

class Animal{
    String name;
    String sex;
    int age;
    public void sleep(){}
}
class Cat extends Animal{
    public void eat(){
        System.out.println("吃猫粮");
    }
    public void speak(){
        System.out.println("喵");
    }
}

class Dog extends Animal{
    public void eat(){
        System.out.println("吃狗粮");
    }
    public void speak(){
        System.out.println("汪");
    }
}

对程序进行debug一下: 

发现实例化出来的猫和狗对象中仍有相关的属性。

其中:Animal类称为父类/基类或超类,Dog和Cat可以称为Animal的 子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可

从继承概念中可以看出继承最大的作用就是:实现代码复用,还有就是来实现多态

子类中访问父类成员

对于子类从父类中继承而来的变量有三种情况。

1.子类中有的变量

2.子类中没有,父类中有的变量

3.子类中的与父类中的同名的变量

这三种情况下子类中的变量应该如何进行访问,我们用一段代码来进行解释:

public class Javabit_Code{
    public static void main(String[] args) {
        Derived der=new Derived();
        System.out.println(der.a);
        System.out.println(der.b);
        System.out.println(der.c);
        System.out.println(der.d);
        System.out.println("============");
    }
}
class Base{
    int a=10;
    int b=10;
    int d=10;
}
class Derived extends Base{
    int a=20;
    int c=20;
    double d=20;
}

运行结果如图所示:

 通过a和c输出的值可以看出不管父类中有没有,只要子类中有那就优先访问子类中的变量。

由b可知,当子类中没有时会访问父类中的变量。

由d可知,如果父类和子类中有同名的变量,当类型不同时也是优先访问子类的变量。

super关键字

我们一定会有一个需求,那就是虽然子类中有这个变量名的变量,但我仍需要父类中的这个变量的数据,但由于我的子类中有这个变量了,我无法对父类中的那个变量进行直接访问,为了解决这一问题,super关键字诞生了。

class Base{
    int a=10;
    int b=10;
    int d=10;
}
class Derived extends Base{
    int a=super.a;
    int c=20;
    double d=20;
}

 输出结果:

子类构造方法

在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执 行子类的构造方法,因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子 肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整 ,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整

class Base{
    int a=10;
    int b=10;
    int d=10;
    Base(){}
    Base(int a,int b){
        this.a=a;
        this.b=b;
    }
}
class Derived extends Base{
    int a=20;
    int b=20;
    int c=20;
    double d=20;
    Derived(){}//没有写super是因为父类中有无参的构造方法,实际上有super()只是省略了
    Derived(int a,int b,int c){
        super(a,b);
        this.c=c;
    }
}

子类的初始化过程——代码的执行顺序

现在我们已知的类在加载和实例化对象的过程中,有静态代码块,实例代码块,构造方法和成员变量等,那么他们在这一过程中的执行顺序是什么?或者说一个类从被加载到实例化一个对象他都进行了那些步骤?

public class Javabit_Code{
    public static void main(String[] args) {
        Derived der1=new Derived();
        System.out.println("==================");
        Derived der2=new Derived();
    }
}
class Number{
    public Number(){
        System.out.println("Number的构造方法");
    }
}
class Base{
    Number num=new Number();
    public Base(){
        System.out.println("父类的构造方法");
    }
    //实例代码块
    {
        System.out.println("父类的实例代码块");
    }
    //静态代码块
    static {
        System.out.println("父类的静态代码块");
    }
}
class Derived extends Base{
    public Derived(){
        System.out.println("子类的构造方法");
    }
    //实例代码块
    {
        System.out.println("子类的实例代码块");
    }
    //静态代码块
    static {
        System.out.println("子类的静态代码块");
    }
}

 运行结果如图所示:

 由此我们可以得出结论:

1、父类静态代码块优先于子类静态代码块执行,且是最早执行。

2、父类实例代码块和父类构造方法紧接着执行。

3、子类的实例代码块和子类构造方法紧接着再执行。

4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行。

用父类的构造方法(super)初始化父类的成员变量,然后子类在 初始化自己独有的成员变量。

类从加载到实例化的大体流程

一个java文件被javac编译成.class字节码文件——》需要new一个对象的时候先检测类是否已经加载,没有加载则加载——》类加载并被放入jvm的同时会初始化静态变量,执行静态代码块——》为实例化的对象分配内存空间——》处理并发安全问题——》初始化所分配的空间即为成员变量默认初始化——》设置对象头信息——》先调用实例代码块在调用构造方法给对象中的各个成员赋值。

举个栗子

class X{
	Y y=new Y();
	public X(){
		System.out.print("X");
	}
}
class Y{
	public Y(){
		System.out.print("Y");
	}
}
public class Z extends X{
	Y y=new Y();
	public Z(){
		System.out.print("Z");
	}
	public static void main(String[] args) {
		new Z();
	}
}

这段代码的运行结果是YXYZ。

执行顺序:new一个Z对象——》Z继承X——》先将X的成员构造完整——》调用了Y的构造方法输出了一个Y——》X的构造方法中也输出了一个X——》回到Z,将Z中的成员构造完整——》调用Y在输出一个Y(此时的Y对象为子类的Y对象,与从父类继承的Y对象同名但不相同)——》Z中的构造方法输出一个Z。

以上就是我关于继承的讲解,如果对你有帮助还请三连,如果疏漏,欢迎大佬指正!

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

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

相关文章

nginx(六十八)proxy模块(八)nginx与上游的ssl握手

一 nginx作为客户端与上游的SSL/TLS握手 理解上: nginx作为客户端,此时类似浏览器的角色,发请求建立连接 nginx作为server端与下游进行SSL/TLS握手 ① nginx与后端选择什么样的协议 1)如果nginx与上游是局域网内,一般通过http建立请求,不需要进行…

详解__int128,最大可用整数类型

前言:有些题目需要的数值刚好比 long long 的最大值大那么一点点,那么我们就可以用__int128 来搏一搏(并不是所有OJ都支持这个数据类型,受编译标准影响) 最大值是多少 int 最大值:2^(32-1)-1【受电脑字长影…

碳中和专题:碳足迹核算、碳中和顶刊论文、碳排放交易2022

(1)碳中和顶刊论文 1、数据来源:自身 2、具体内容: 01周宏春:碳循环经济内涵、实践及其碳中和的深远影响.pdf 02谢和平:碳中和目标下煤炭行业发展机遇.pdf 03秦阿宁:碳中和背景下的国际绿色技…

【FPGA】基于状态机实现自动售货机模拟

文章目录一、售货机功能二、售货机状态分析及模块划分三、代码实现四、上板验证一、售货机功能 此自动售货机模拟基于EP4CE6F17C8开发板实现,用按键,led灯,数码管表示各个输入输出 功能: 此自动售货机可以选择A(三元…

[激光原理与应用-21]:《激光原理与技术》-7- 激光技术大汇总与总体概述

目录 前言: 第1章 什么是激光技术 1.1 什么是激光技术 1.2 激光技术的分类方法 第2章 激光的应用技术 2.1 激光加工技术 2.2 激光快速成型 2.3 激光切割 2.4 激光焊接 2.5 激光雕刻 2.6 激光打孔 2.7 激光蚀刻 2.8 激光手术 2.9 激光武器 2.10 激光能…

详解诊断数据库ODX-D

文章目录 前言一、ODX-D具体内容是什么?二、ODX企标中关于ODX-D定义内容三、ODX-D在CANdelaStudio以及ODXStudio中定义内容总结前言 ​又是一周末,静下心码下字,将ODX这个Topic补充完整。 ODX含义是开放式诊断数据交互,是欧洲那边提出诊断数据架构,详情可如下图: 核心…

区间信息维护与查询【树状数组 】 - 原理2 多维树状数组

区间信息维护与查询【树状数组 】 - 原理2 多维树状数组 我们已经知道一维树状数组修改和查询的时间复杂度均为O (logn),可以扩展为m 维树状数组,其时间复杂度为O (log ^m n ),对该算法只需加上一层循环即可。二维数组a [n ][n ]、树状数组c…

创建TCP通信与粘包问题解决

创建TCP通信 nodeJS的Net模块实现了底层通信接口 通信过程 创建服务端:接收和回写客户端数据创建客户端:发送和接收服务端数据数据传输: 内置服务事件和方法读写数据 通信事件 listing事件:调用server.listen方法之后触发con…

介绍 10 个有用的 Flutter 软件包

介绍 10 个有用的 Flutter 软件包 原文 https://genotechies.medium.com/introducing-10-useful-flutter-packages-1252c4b75fa7 前言 FLutter 软件包使您的开发简单快速。然而,有利有弊。有时候,如果从头开始开发这个特性将是有益的,因为可定…

Hive日分区表如何快速导入到StarRocks

1、背景 业务现状:集团使用FineBI做数据呈现及报表分析工具,经过近两年的BI建设,供应链域及营销域的BI建设已初具规模并体系化。数仓规模60TB,FineBI数据集约8000个,BI挂出报表数约1600个,报表月增幅在40左…

非凡社群管理之社群管理有什么内容

社群作为一个非常重要的私域流量池,它本身就是一个提升用户价值的利器。但如果管理不好社群,那么也是无济于事的。 社群小助手提示:高效管理社群,以下这五个方面要做好。 一,社群为用户解决问题,让群成员都…

iwebsec靶场 SQL注入漏洞通关笔记6- 宽字节注入

系列文章目录 iwebsec靶场 SQL注入漏洞通关笔记1- 数字型注入_mooyuan的博客-CSDN博客 iwebsec靶场 SQL注入漏洞通关笔记2- 字符型注入(宽字节注入)_mooyuan的博客-CSDN博客 iwebsec靶场 SQL注入漏洞通关笔记3- bool注入(布尔型盲注&#…

【ML特征工程】第 7 章 :通过K-Means 模型堆叠进行非线性特征化

🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃 🎁欢迎各位→点赞…

计算机视觉之目标检测(object detection)《1》

在计算机视觉领域,除了识别图像并分类之外,我们很多时候想关注图像里面一些感兴趣的目标,比如视频监控中寻找一个或多个嫌疑犯;无人驾驶需要识别车辆、行人、红绿灯、路障等等,都是需要去及时掌握画面中的不同目标。我…

古瑞瓦特能源通过聆讯:上半年营收23亿 IDG投资9亿持股6.5%

雷递网 雷建平 11月26日古瑞瓦特能源(简称:“Growatt Technology”)日前递交招股书,准备在香港上市。上半年营收23.45亿古瑞瓦特能源于2011年在深圳成立,是一家分布式能源解决方案提供商,专注于可持续能源发…

Crack:GoJS 2.2.18 -2022-09-08 update

使用 JavaScript 和 TypeScript 为 Web 构建图表 流程图 构建交互式流程图或流程图。让您的用户使用 JSON 模型输出构建、修改和保存图表。状态图 可视化状态图和其他行为图。创建具有实时更新的图表以监控状态,或创建交互式图表以进行规划。桑基图 GoJS 允许对链接…

史上最全MATLAB误差分析工具箱,不看别后悔 【矢量化代码、效率嘎嘎快、支持计算50种指标】

在拟合、插值、模拟预测等计算中,往往需要通过不同指标参数来分析实际值与计算值之间差异依次衡量相关方法的可行性。常用的表征指标有残差平方和(SSE)、均方差(MSE)、均方根差(RMSE)、平均绝对误差(MAE)和决定系数R方(R-Squared)等等。 考虑到误差分析在实际应用中…

Kafka部署安装及简单使用

一、环境准备 1、jdk 8 2、zookeeper 3、kafka 说明:在kafka较新版本中已经集成了zookeeper,所以不用单独安装zookeeper,只需要在kafka文件目录中启动zookeeper即可 二、下载地址 Apache Kafka 三、部署 1、启动zookeeper -- 启动 .…

CSDN第11次竞赛题解与总结

CSDN第11次竞赛题解与总结前言建议题解T1圆小艺扩展完整代码T2K皇把妹完整代码T3筛选宝物完整代码T4圆桌完整代码总结前言 2022/11/27 CSDN第11次竞赛 由「壹合原码 & CSDN」联合主办 本次奖励还是不错的 (毕竟有赞助商),前三十名都有奖励,连以前第…

跑步10年回望

回顾跑步这10年有点遗憾,最终还是决定放弃参加2022年厦马,因为要求更早到厦门,也担心回福州后影响小朋友上课,权衡之下还是决定申请退赛。本想在这次活动上实现全马破4的目标,却只能晒个退赛截图。。。今年是厦马20年&…