【从零开始学习JAVA | 第十四篇】继承

news2025/1/17 0:05:31

目录

前言: 

引入:

继承:

小拓展:

优点:

 成员方法的继承问题:

总结:


前言: 

 继承是面向对象三大特性之一,它是在封装之后我们讲解的一个重要的性质,继承是类与类之间的关系,子类会继承父类中对子类开放的成员函数以及成员方法。这大大优化了我们在写代码时候的复用性,因此我们要学好继承,这样才可以学好JAVA

引入:

如果此时我们要创建一个学生类,它的成员变量包括姓名,年龄,性别,成员行为包括吃饭,玩游戏,睡觉,学习,要创建一个教师类,它的成员变量包括姓名,年龄,性别,成员行为包括吃饭,玩游戏,睡觉,教学,放到以前我们会这样建立:

但是我们会发现,其实这两个类的行为都是高度相似的,那么我们能否精简一下呢?
这里就用到我们之前说的继承,我们抽象出来一个父类概括这两个类之间的共同点,然后然这两个类继承父类,这样不就降低了代码的复用性。

 其实这就是继承的思想:把类之间的相似点抽象出来,建立一个可以继承的父类,以此来降低代码的复用性。

继承:

Java中,继承是面向对象编程中的重要概念之一,它是指一个类可以继承另一个类的属性和方法,同时可以添加或覆盖父类的功能,从而创建一个新的类。通过继承,子类可以获得父类的全部或部分特性,从而减少代码的重复,简化程序的设计,提高代码的可重用性。

在Java中,一个子类通过  extends  关键字继承一个父类。子类可以访问父类中的公有和受保护的成员变量和方法,但不能访问父类的私有成员变量和方法。子类可以覆盖父类的方法,实现自己特定的行为,或者添加新的方法和属性。

以下是一个简单的Java类继承的示例:

class Animal {
    String name;
    int age;
    void eat() {
        System.out.println("Animal is eating");
    }
}

class Cat extends Animal {
    void meow() {
        System.out.println("Cat is meowing");
    }
}

public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.name = "Tom";
        cat.age = 2;
        cat.eat();
        cat.meow();
    }
}

在上述示例中,Cat类继承了Animal类,并添加了一个自己的方法meow。在主程序中,我们创建一个Cat类的对象,并可以访问Animal类的属性和方法,并且可以调用Cat类自己的方法。

小拓展:

JAVA和C++的继承方式非常相似,但是在java中,所有的继承都是公共继承,不存在保护继承和私有继承

在 Java 中,继承可以分为公有继承受保护继承

公有继承(public inheritance)是指子类可以继承父类的公有成员和受保护成员,而不能继承父类的私有成员。

受保护继承(protected inheritance)是指子类可以继承父类的公有成员和受保护成员,但不能直接访问父类的私有成员。(只是不能直接访问而已,在后面我们会介绍方式访问)

实际上,在 Java 中不需要特别声明继承方式,默认使用公有继承。Java 中所有成员变量和方法都有一个访问修饰符,如public、private和protected等,通过使用不同的访问修饰符可以限制子类的访问范围。同时,Java提供了一些关键字,如final和static等,可以在继承时进行限制或定义。

*受保护继承(JAVA)   不是      保护继承(C++)

受保护继承    会把父类的私有成员继承给子类,子类不能直接访问,可以间接访问

保护继承    会把父类的所有成员都继承给子类(私有成员也继承),只不过子类不会提供调                    用的函数,也就相当于没有继承。

如果不相信我们可以调用 vs 2022 管理员后台,进行验证,这里篇幅有限,就不进行验证了。

如何在子类中访问父类中private的变量呢?

如果需要在子类中访问父类的私有变量,可以使用Java中提供的getter和setter方法,通过调用父类的公有方法来实现。

比如,我们在父类中声明了一个私有变量:

public class Parent {
    private int x;
    public Parent(int x) {
        this.x = x;
    }
    private int getX() {
        return x;
    }
}

可以在父类中添加一个公有的getter方法getX(),用于获取私有变量x的值:

public class Parent {
    private int x;
    public Parent(int x) {
        this.x = x;
    }
    private int getX() {
        return x;
    }
    public int getPrivateVariableX() {
        return this.getX();
    }
}

子类可以通过调用父类的公有方法getPrivateVariableX()来获取父类的私有变量x的值:

public class Child extends Parent {
    public Child(int x) {
        super(x);
    }
    public int getPrivateVariableX() {
        return super.getPrivateVariableX();
    }
}

这样就可以在子类中获取并使用父类中的私有变量x了。但是需要注意的是,私有变量在父类中是被限制了访问权限的,而在子类中通过公有方法来访问,可能会造成访问权限的漏洞,因此需要特别注意。

优点:

继承是面向对象程序设计中的一个重要特性,具有以下优点:

1. 代码重用:通过继承,可以将现有的类的代码和功能复用在新的类中,避免了重复编写代码造成资源浪费的问题,提高了代码的复用性。

2. 继承关系体现了程序中的真实的关系:继承关系可以清晰地表示父类与子类之间的关系,从而提高程序的可读性和可维护性。

3. 扩展性好:通过继承可以很方便地扩展一个类并增加新的特性,同时又不会影响到现有的代码和已有的功能。

4. 多态性:通过继承和子类的多态特性,可以使代码更加灵活和可扩展。

5. 代码封装:继承提供了一种封装的方式,父类中的成员可以在子类中被重用,并且对外不可见,保证了代码的安全性和隐私性。

总之,通过继承可以相对简单地实现代码的重用和扩展,使代码更加灵活、可读性更高,并且可以提高代码的可维护性。

介绍到这里,很多小伙伴都会陷入到一个误区既然继承这么便洁,我们以后遇到创建多个类就进行抽象父类,再把父类继承给子类。

这种思想是错误的!这是因为虽然继承很方便,但是我们的父类应该是与子类有一定的相连关系的,这样做是为了提高代码的可读性,例如我们把动物抽象出来,继承给小猫,小狗这样的子类,把手机抽象出来,继承给小米,华为,苹果这样的子类。而不可以随意抽象父类。

JAVA中只支持单继承,不支持多继承,但支持多层继承。

翻译一下:A不可以同时继承B,C(不支持多继承).但是可以让C继承B,A再继承C(多层继承)。

其实这个特性是为了解决C++中的多继承带来的缺陷:如果两个父类的方法名称相似,那么我们的子类如果继承了这两个父类,在调用这个方法的时候,我们到底调用的是哪一个父类中的方法呢?
c++给出的答案是 虚继承

虚继承是指在继承的时候使用关键字  virtual  ,这样的继承方式可以避免派生类继承多个基类中的同名成员(数据和函数)造成的歧义。这是因为虚继承会让派生类只在其继承树中保存一个唯一的基类子对象,从而消除了重复继承的成员。

例如,假设有两个基类A和B,它们都有一个同名函数f(),如果一个类C继承了A和B,那么在调用C::f()时,会发生二义性问题。但如果A和B被虚继承,那么C类只继承一个A子对象和一个B子对象,这样C::f()就不会被重复继承。如果需要在C中调用A或B中的f()函数,可以通过作用域解析符(::)指定调用某个基类的函数,在调用时指定基类A或B即可。

以下是一个示例代码:

class A {
public:
    virtual void f() {
        cout << "A::f()" << endl;
    }
};

class B {
public:
    virtual void f() {
        cout << "B::f()" << endl;
    }
};

class C: public virtual A, public virtual B {
public:
    virtual void f() {
        A::f(); // 调用A的f()函数
        B::f(); // 调用B的f()函数
    }
};

int main() {
    C c;
    c.f(); // 输出 A::f() B::f()
    return 0;
}

而我们的JAVA为了避免这一个繁琐的步骤,就直接禁止了子类进行多父类继承的能力。

 其实每一个类都会直接或间接的继承Object。

在Java中,Object是所有类的根类。Java语言是一门面向对象的语言,所有的类都直接或间接继承了Object类,因此Object类在Java程序中是非常重要和基础的。

Object类定义了一些通用的方法,如:

  • toString()方法:用于返回对象的字符串表示,通常被子类重写。
  • equals()方法:用于比较两个对象是否相等。
  • hashCode()方法:用于返回对象的哈希码,通常被重写。

此外,Object类还定义了一些其他常用的方法,如getClass()方法用于获取对象的类,notify()、notifyAll()和wait()等方法用于线程同步等。

需要注意的是,Object类型是Java中的顶级类型,不是基本类型。在Java中,有八种基本数据类型:byte、short、int、long、float、double、boolean和char。尽管Object类是Java中非常重要的类,但也不要滥用Object类型,尽量使用具体的子类,以便程序具有更好的类型安全性和可读性。

 成员方法的继承问题:

 如果 A 到 D 逐层继承,那么如果我们在A中调用方法C,他真的会逐级父类去找方法D嘛?

实际上是不会这样的,我们有一个虚方法表,各个父类会将自己的方法添加到虚函数表中,供调用的时候快速查询。

虚方法表中的方法必须是:

  • 非private:private关键字修饰的方法只能在本类中访问,无法被子类继承,因此不可能成为虚方法,也不会在虚方法表中存储。

  • 非static:静态方法是属于类而不是对象的,不能被子类继承,因此也不可能成为虚方法,也不会在虚方法表中存储。

  • 非final:final关键字修饰的方法是不能被子类重写的,因此也不可能成为虚方法,也不会在虚方法表中存储。

需要注意的是,在Java中,虚方法表是在运行时动态生成的,基于实际的对象类型,而不是变量的声明类型。这是Java实现多态性的一种高效的方式,可以使程序实现运行时动态绑定,提高代码的可维护性和可扩展性。

2.子类继承父类构造方法的问题:

1.子类不能继承父类的构造方法,但是可以通过super调用

2.子类构造方法的第一行,一定是一个super();这是因为子类的构造中可能会用到父类的成员变量,如果父类不先进行构造,直接运用在子类的构造中,可能会出错。

3.要想super调用父类的有参构造,必须手动书写

总结:

继承是类与类之间的关系,而继承隶属于面向对象的三大特性之一,是一个很重要的性质。因此我们要学好这一个知识点,这样才可以玩转JAVA

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

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

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

相关文章

在github上创建个人主页的方法【2023更新版】

01-进入github的网站&#xff0c;链接 https://github.com/ &#xff0c;然后注册&#xff0c;登陆&#xff0c;注意登陆时设置的用户名(username)就是将来你个人主页的三级域名&#xff0c;所以这里一定要慎重填写username。如下图所示&#xff1a; 02-注册完成后进入个人主…

2024考研408-计算机组成原理第四章-指令系统

文章目录 前言一、指令系统现代计算机的结构1.1、指令格式1.1.1、指令的定义1.1.2、指令格式1.1.3、指令—按照地址码数量分类①零地址指令②一地址指令&#xff08;1个操作数、2个操作数情况&#xff09;③二地址指令④三地址指令⑤四地址指令 1.1.4、指令-按照指令长度分类1.…

【计算机组成原理】Yy-z02模型机的硬布线控制器设计

目录 一、Yy-z02模型机的系统结构 二、Yy-z02模型机的数据通路 三、Yy-z02模型机的指令执行 四、Yy-z02模型机的硬布线控制器 一、Yy-z02模型机的系统结构 指令系统的实现 <--- 构造它的硬件系统 硬件系统构造过程&#xff1a; 分析指令格式和各指令的功能确定部件连…

金蝶软件遭遇.locked勒索病毒攻击:如何保护与解救您的数据?

引言&#xff1a; 近期&#xff0c;部分运行金蝶云星空软件的服务器遭受了一场勒索病毒的网络安全攻击&#xff0c;其重要数据遭到了.locked勒索病毒的加密。作为一个知名的企业级ERP软件及财务软件&#xff0c;金蝶软件的数据安全事关客户和企业的利益。91数据恢复在本文将深…

【王道·操作系统】第四章 文件管理【未完】

一、初识文件管理 文件&#xff1a;一组有意义的信息/数据集合文件属性&#xff1a; 文件名&#xff1a;创建文件的用户决定&#xff0c;主要是为了方便用户找到文件&#xff0c;同一目录下不允许有重名文件标识符&#xff1a;一个系统内的各文件标识符唯一&#xff0c;对用户来…

老大给了个新需求:如何将汉字转换成拼音字母?1行Python代码搞定!

大家好&#xff0c;这里是程序员晚枫&#xff0c;小红薯也叫这个名。 之前的视频给大家分享了&#xff1a;中文编程&#xff0c;一行代码实现。 今天给大家分享一下&#xff0c;如何通过1行Python代码&#xff0c;实现汉语转拼音 1、先上代码 实现汉语转拼音效果的第三方库…

逻辑回归(Logistics Regression)

1.逻辑回归&#xff08;Logistics Regression&#xff09; 逻辑回归用于解决二分类问题 1.1 Sigmoid函数 sigmoid函数在神经网络中如何起作用&#xff1f;详见本人笔记&#xff1a;机器学习和AI底层逻辑 复杂非线性分类->多个线段->每个线段是叠加而来的->sigmoid函…

计算机视觉 + Self-Supervised Learning 五种算法原理解析

计算机视觉领域下自监督学习方法原理 导语为什么在计算机视觉领域中进行自我监督学习&#xff1f; 自监督学习方法Generative methodsBEiT 架构 Predictive methodsContrastive methodsBootstraping methodsSimply Extra Regularization methods 导语 自监督学习是一种机器学习…

Web服务器群集:Nginx网页及安全优化

目录 一、理论 1.Nginx网页优化 2.Nginx安全优化 3.Nginx日志分割 二、实验 1.网页压缩 2.网页缓存 3.连接超时设置 4.并发设置 5.隐藏版本信息 6.脚本实现每月1号进行日志分割 7.防盗链 三、总结 一、理论 1.Nginx网页优化 &#xff08;1&#xff09;概述 在企…

神仙打架的618,谁才是真正的大赢家?

618大促已经缓缓落下帷幕&#xff0c;各大平台和品牌方准时准点晒出成绩单。在一串又一串红彤彤的战报中&#xff0c;家电品牌你追我赶的激烈战况一如以往。 我们从中也得以窥见新消费时代下中国家电行业的未来&#xff0c;尤其是在消费者纷纷捂紧钱袋子的今年&#xff0c;红色…

快解析域名映射,通过外网域名来访问内网

在本地搭建主机应用后&#xff0c;由于没有公网IP或没有公网路由权限&#xff0c;在需要发布互联网时&#xff0c;就需要用到外网访问内网的一些方案。由于内网IP在外网不能直接访问&#xff0c;通常就用通过外网域名来访问内网的方法。那么&#xff0c;公网域名如何解析到内网…

无法开启nginx -t等命令的解决办法

在 Windows 下载安装了 Nginx&#xff0c;配置了环境变量全局使用 Nginx。但是仍旧无法开启nginx -t等命令。 原因&#xff1a; Nginx 在使用时 conf-path 是根据相对路径来找的。 匹配的路径是 C:\Users\20210121/conf/nginx.conf &#xff0c;完全是错的。 解决办法&#x…

Redis进阶 - Redis持久化

原文首更地址&#xff0c;阅读效果更佳&#xff01; Redis进阶 - Redis持久化 | CoderMast编程桅杆https://www.codermast.com/database/redis/redis-advance-persistence.html 单点Redis的问题 数据丢失问题&#xff1a;Redis 是内存存储&#xff0c;服务重启可能会丢失数据。…

基于卷积神经网络的高光谱图像分类

文章目录 引言1. 基于光谱特征2. 基于空间特征3. 基于空谱特征3.1 空间特征和光谱特征的融合3.2 基于3D-CNN分类 4. 总结 引言 近年来深度学习的技术在计算机视觉领域中大放异彩&#xff0c;使得对多光谱数据分类的研究迅速发展&#xff0c;结合2D-CNN&#xff0c;3D-CNN&…

数据结构第六章 图 6.4 错题整理

4.A A. 不是简单路径的话&#xff0c;有环&#xff0c;去环路径会更短 B. 适合的 弗洛伊德算法才不适合 C. 本来就是 D 2X2矩阵拓展到3X3矩阵 再扩大 若是子集 即加入新顶点后&#xff0c;最短路径都没有变&#xff0c;错 5.B 本题用弗洛伊德更合适 但这道题只需全部代入求最…

xml系列篇之xml建模

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于xml的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 是什么 为什么要使用xml建模 怎么使用 1.…

NodeJS Mocha测试⑩④

文章目录 ✨文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持&#x1f618;前言Mocha 1、编写测试 2、SumJS代码 3、使用内置断言库 4、第三方库 chai断言库 5、第三方库 异步断言 6、http测试 7、钩子函数更多包工具总…

【Linux系统命令】——平均负载分析,以及cpu的性能检测,进程上下文切换分析

目录 1 平均负载 1.1概念 1.2 uptime指令&#xff08;检测平均负载&#xff09; 1.3 负载分析 1.4 单核cpu负载分析 1.5 不同时间内的load值分析 1.6 平均负载和cpu使用率的区别 2. 压测命令 2.1 对cpu进行压力测试 2.2 对内存进行压力测试 2.3对磁盘压力测试 2.…

RocketMQ常用操作

RocketMQ历史及发展 如果想要了解RocketMQ的历史&#xff0c;则需了解阿里巴巴中间件团队中的历史 2011年&#xff0c;Linkin(领英&#xff1a;全球知名的职场社交平台)推出Kafka消息引擎&#xff0c;阿里巴巴中间件团队在研究了Kafka的整体机制和架构设计之后&#xff0c;基…

NCI-2

10.5 NFCEE 状态 NFCC 使用此控制消息向 DH 通知启用的 NFCEE 状态的变化。 NFCC 发送 NFCEE_STATUS_NTF 来报告启用的 NFCEE 状态的变化。 对于任何禁用或无响应的 NFCEE&#xff0c;NFCC 不应发送 NFCEE_STATUS_NTF。 当启用 NFCEE 并且 NFCC 检测到与该 NFCEE 通信时存在不…