【JavaSE】_继承

news2024/11/18 21:51:30

目录

1.继承的概念

2. 继承语法

3. 父类成员的访问

3.1 子类中访问父类的成员变量

3.1.1 子类和父类不存在同名成员变量

3.1.2 子类和父类成员变量同名

3.2 子类中访问父类的成员方法

3.2.1 成员方法名不同

3.2.2 成员方法名相同

4. super关键字

5. 子类构造方法

6. 再谈初始化

7. protected 关键字

8. 继承方式

9. final 关键字

9.1 修饰变量或字段

9.2 修饰类

10. 继承与组合


1.继承的概念

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

继承主要解决的问题是:共性的抽取,实现代码复用;

2. 继承语法

在java中,表示类的继承关系需要使用到exends关键字

修饰限定符 子类 extends 父类{
   //...
}
class Animal{
    public String name;
    public int age;
    public void  fun1(){
        System.out.println("It is an animal.");
    }
}
class Dog extends Animal{
    public void Bark(){
        System.out.println("The dog named " +name+" is barking.");
    }
}
class Cat extends Animal{
    public void Meow(){
        System.out.println("The cat named "+ name+" is meowing.");
    }
}
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.fun1();
        dog.name = "Mike";
        dog.Bark();
        Cat cat = new Cat();
        cat.fun1();
        cat.name= "Mary";
        cat.Meow();
    }
}

 输出结果为:

 注:(1)子类会将父类中的成员变量或成员方法继承到子类中;

(2)子类继承父类之后,必须要新增自己特有的成员以体现与父类的不同,否则不需要继承;

3. 父类成员的访问

3.1 子类中访问父类的成员变量

3.1.1 子类和父类不存在同名成员变量

class Base{
    public int a = 10;
    public int b = 20;
    }
    class Derived extends Base{
    public int c = 30;
    public void fun(){
        System.out.println("a = "+a);
        System.out.println("b = "+b);
        System.out.println("c = "+c);
    }
    }
public class Main {
    public static void main(String[] args) {
        Derived derived  = new Derived();
        derived.fun();
    }
}

输出结果为:

  

结论1:当子类当中不存在与父类同名的属性,在子类内读写属性时,如果子类中存在该属性则直接读取,如果子类当中不存在该属性就去父类当中寻找; 

3.1.2 子类和父类成员变量同名

class Base{
    public int a = 10;
    public int b = 20;
    }
    class Derived extends Base{
    public int a = 100;
    public int b = 200;
    public int c = 30;
    public void fun(){
        System.out.println("a = "+a);
        System.out.println("b = "+b);
        System.out.println("c = "+c);
    }
    }
public class Main {
    public static void main(String[] args) {
        Derived derived  = new Derived();
        derived.fun();
    }
}

输出结果为:

结论2:当子类当中存在与父类同名的属性,当在子类内读写属性时,会优先读取子类的属性; 

如果需要指定访问父类中的属性,则需使用super关键字

class Base{
    public int a = 10;
    public int b = 20;
    }
    class Derived extends Base{
    public int a = 100;
    public int b = 200;
    public int c = 30;
    public void fun(){
        System.out.println("a = "+ super.a);
        System.out.println("b = "+ super.b);
        System.out.println("c = "+c);
    }
    }
public class Main {
    public static void main(String[] args) {
        Derived derived  = new Derived();
        derived.fun();
    }
}

输出结果为:

注:结论2:当在子类内读写属性时,如果依次在子类、父类中都查询无果,则会编译报错;

3.2 子类中访问父类的成员方法

3.2.1 成员方法名不同

class Base{
    public int a = 10;
    public int b = 20;
    public void methodBase(){
        System.out.println("Base function.");
    }
    }
    class Derived extends Base{
    public int a = 100;
    public int b = 200;
    public int c = 30;
    public void methodDerived(){
        System.out.println("Derived function.");
    }
    public void fun1(){
        methodBase();
        methodDerived();
    }
    }
public class Main {
    public static void main(String[] args) {
        Derived derived  = new Derived();
        derived.fun1();
    }
}

输出结果为:

3.2.2 成员方法名相同

class Base{
    public int a = 10;
    public int b = 20;
    public void methodBase(){
        System.out.println("Base function(methodBase).");
    }
    }
    class Derived extends Base{
    public int a = 100;
    public int b = 200;
    public int c = 30;
    public void methodDerived(){
        System.out.println("Derived function.");
    }
    public void methodBase(){
        System.out.println("Derived function(method Base).");
    }
    public void fun1(){
        methodBase();
    }
    }
public class Main {
    public static void main(String[] args) {
        Derived derived  = new Derived();
        derived.fun1();
    }
}

输出结果为:

在子类中访问父类方法与在子类中访问父类属性的规则相同,就近访问子类的方法,如果该方法在子类中不存在就去父类中查询,如果两个类都查询无果则报错;同样,在子类访问与父类同名的方法时如需指定访问父类方法则需使用super关键字:

class Base{
    public int a = 10;
    public int b = 20;
    public void methodBase(){
        System.out.println("Base function(methodBase).");
    }
    }
    class Derived extends Base{
    public int a = 100;
    public int b = 200;
    public int c = 30;
    public void methodDerived(){
        System.out.println("Derived function.");
    }
    public void methodBase(){
        System.out.println("Derived function(method Base).");
    }
    public void fun1(){
        super.methodBase();
    }
    }
public class Main {
    public static void main(String[] args) {
        Derived derived  = new Derived();
        derived.fun1();
    }
}

输出结果为:

注:

class Base{
    public void methodBase(){
        System.out.println("Base function(methodBase).");
    }
    }
    class Derived extends Base{
    public void methodBase(int a){
        System.out.println("Derived function(method Base).");
    }
    public void fun1(){
        methodBase();
    }
}

在上文代码中:

分别位于父类和子类中的methodBase方法构成重载

② 由于子类中的该方法需要一个int型参数,而在调用时并未传参,故而无需使用super.methodBase,也调用的是父类的该方法:

  

在java官方文档中关于重载的定义如下:

详见: https://docs.oracle.com/javase/specs/index.html

4. super关键字

在上文已介绍,super关键字的主要功能是:在子类中指定访问父类的属性或方法:

super.data:在子类当中访问父类的成员属性;

super.func():在子类当中访问父类的成员方法;

注:① 只能在非静态方法内使用;

② 在子类方法中访问父类的属性或方法;

5. 子类构造方法

子类对象构造时需要先调用其父类的构造方法,然后再执行子类的构造方法;

class Animal{
    public String name;
    public int age;
    public void  fun1(){
        System.out.println("It is an animal.");
    }
    public Animal(){
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
class Dog extends Animal{
    public String breed;
    public Dog(String name,int age,String breed){
        super(name,age);
        //显式调用父类构造方法对父类成员进行初始化
        this.breed = breed;
    }
    public void Bark(){
        System.out.println("The dog named " +name+" is barking.");
    }

    @Override
    public String toString() {
        return "Dog{" +
                "breed='" + breed + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
class Cat extends Animal{
    public String color;
    public Cat(String name,int age,String color){
        //super();
        //当父类拥有无参构造方法时,编译器会默认给子类增加一个父类的构造方法
        // 此时可以不再显式书写super();
        super(name,age);    //为传参完整,此处以带参父类构造方法为例
        this.color = color;
    }
    public void Meow(){
        System.out.println("The cat named "+ name+" is meowing.");
    }

    @Override
    public String toString() {
        return "Cat{" +
                "color='" + color + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Mike",5,"Labrador");
        System.out.println(dog);
        Cat cat = new Cat("Mary",5,"grey");
        System.out.println(cat);
    }
}

输出结果为:

注:(1)子类调用父类构造方法时必须将super语句放在子类构造函数的第一行,否则就会报错;

(2)super(...)只能在子类构造方法中出现一次且与this不能同时出现;

(3)当没有在父类中显式书写带参构造方法时,编译器会默认增加一个无参的构造方法,故而建议在编写类尤其是有可能发生继承拥有子类时,重载一个无参的构造方法与一个带参的构造方法;

6. 再谈初始化

class Animal{
    public String name;
    public int age;
    //静态代码块
    static{
        System.out.println("Animal static{}");
    }
    //实例代码块
    {
        System.out.println("Animal{}");
    }
    //无参构造方法
    public Animal(){
        System.out.println("Animal(){}");
    }
}
class Dog extends Animal{
    public String breed;
    //无参构造方法
    public Dog(){
        System.out.println("Dog(){}");
    }
    //静态代码块
    static{
        System.out.println("Dog static{}");
    }
    //实例代码块
    {
        System.out.println("Dog {}");
    }
}
public class Main {
    public static void main(String[] args) {
        Dog dog1 = new Dog();
        System.out.println("------------");
        Dog dog2 = new Dog();
    }
}

输出结果为:

7. protected 关键字

创建如下包与类:

   

(1)同一包中的不同类:

试运行以下代码:

 以上代码可以正常运行,说明protected修饰的属性在同一包中的不同类中可以进行访问;

(2)不同包中的子类:

注:(1)上文代码的前提是TestDemo1类是public修饰的;

(2)private修饰的成员不是没有被继承,而是继承了无法访问;

8. 继承方式

(1)在Java中只支持以下几种继承方式:

单继承(B继承A),多继承(C继承B,B继承A),不同类继承同一个类(B和C都继承A);

(2)C++支持多继承,但Java不支持多继承(C继承A和B);

(3)一般我们不希望有超过三层的继承关系,如果想通过语法进行限制,则需使用final关键字;

9. final 关键字

9.1 修饰变量或字段

final int A= 10;  
A=20;

报错如下:

final修饰变量或字段表示常量,代表不能被修改,并建议名称改为大写;

9.2 修饰类

运行如下代码:

final class Animal{
    public String name;
    public int age;
    public Animal(){
        System.out.println("Animal(){}");
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
class Dog extends Animal{
    public String breed;
    public Dog(String name,int age,String breed){
        super(name,age);
        //显式调用父类构造方法对父类成员进行初始化
        this.breed = breed;
    }
    public Dog(){
        System.out.println("Dog(){}");
    }
    public void Bark(){
        System.out.println("The dog named " +name+" is barking.");
    }
}
class Cat extends Animal{
    public String color;
    public Cat(String name,int age,String color){
        super(name,age); 
        this.color = color;
    }
    public void Meow(){
        System.out.println("The cat named "+ name+" is meowing.");
    }

}
public class Main {
    public static void main(String[] args) {
        Dog dog1 = new Dog();
        Dog dog2 = new Dog();

    }
}

报错如下:

final修饰类表示该类不能再被继承;

注:① 如果需要将成员变量定义为final,语法规定必须同时给定一个初始值;

② 运行如下代码:

    public static void main(String[] args) {
        final int[] array = {1,2,3};
        array = new int[10];
    }

报错如下:

因为此时final修饰的是引用array,即array保存的值(指向的对象)是不可以更改的,但是array引用指向对象的内容是可以改变的,即以下代码可以正常运行:

    public static void main(String[] args) {
        final int[] array = {1,2,3};
        array[0]=2;
    }

10. 继承与组合

与继承类似,组合也是一种表示类与类之间关系的方式(a part of);

以教师、学生、学校以及学院类为例:

class Students{   //学生类
}
class Teachers{   //教师类
}
class Campus{
    public Students[] students = new Students[3];
    public Teachers[] teachers = new Teachers[3];
    //将另外一个类作为当前类的一个属性称为组合
}
class academy extends Campus{ //学院类继承学校类
}
public class Main {
    public static void main(String[] args) {
        Campus campus = new Campus();
    }
}

内存分布:

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

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

相关文章

Swin Transformer—— 基于Transformer的图像识别模型

概述 Swin Transformer是微软研究院于2021年在ICCV上发表的一篇论文,因其在多个视觉任务中的出色表现而被评为当时的最佳论文。它引入了移动窗口的概念,提出了一种层级式的Vision Transformer,将Shifted Windows(移动窗口&#x…

Node.js -- 包管理工具

文章目录 1. 概念介绍2. npm2.1 npm 下载2.2 npm 初始化包2.3 npm 包(1) npm 搜索包(2) npm 下载安装包(3) require 导入npm 包的基本流程 2.4 开发依赖和生产依赖2.5 npm 全局安装(1) 修改windows 执行策略(2) 环境变量Path 2.6 安装包依赖2.7 安装指定版本的包2.8 删除依赖2.…

mysql主库delete一个没主键的表导致从库延迟很久问题处理

一 问题描述 发现线上环境一个从库出现延迟,延迟了2天了,还没追上主库。 查看当前运行的sql及事务,发现这个sql语句是在delete一个没主键的表。 二 问题模拟 这里在测试环境复现下这个问题。 2.1 在主库造数据 use baidd; CREATE TABL…

《QT实用小工具·四十三》历史编辑器(支持历史搜索 关键字匹配)

1、概述 源码放在文章末尾 该项目实现了在输入框中输入部分信息能全部展现之前的历史输入信息&#xff0c;支持历史搜索和关键词匹配&#xff0c;项目demo演示如下所示&#xff1a; 项目部分代码如下所示&#xff1a; #include "historymodel.h" #include <QM…

C语言自定义类型【联合体与枚举】

文章目录 1.联合体1.1联合体的声明1.2联合体的特点1.3联合体的大小计算联合体的使用案例 2.枚举2.1枚举类型的声明2.2枚举类型的优点(为什么使用枚举)2.3枚举类型的使用 结语 1.联合体 1.1联合体的声明 和结构体一样&#xff0c;联合体也是由一个或多个成员构成&#xff0c;同…

ffmpeg中stream_loop参数不生效原因分析

问题 使用ffmpeg把一个视频文件发布成一个rtmp流&#xff0c;并设置成循环推流&#xff0c;此时需要使用参数stream_loop&#xff0c;命令如下: ffmpeg.exe -stream_loop -1 -re -i D:\tools\ffmpeg-5.1.2\bin\sei.h264 -c copy -f flv -safe 0 rtmp://localhost:1935/live/te…

BIO、NIO与AIO

一 BIO 同步并阻塞(传统阻塞型)&#xff0c;服务器实现模式为一个连接一个线程&#xff0c;即客户端有连接请求时服务器端就需要启动一个线程进行处理. BIO&#xff08;Blocking I/O&#xff0c;阻塞I/O&#xff09;模式是一种网络编程中的I/O处理模式。在BIO模式中&#xf…

杂项基础知识-部分

** 杂项基础知识 ** 一.常见的各类文件的文件头和文件结尾 列举常见文件头编码特征&#xff1a; JPEG&#xff1a; PNG&#xff1a; GIF&#xff1a; RAR&#xff1a; ZIP&#xff1a; 十六进制特征&#xff1a; 图片文件&#xff1a; JPEG&#xff1a;文件头格式为…

K8s 使用 CephFS 作为后端存储(静态供给、动态供给)

一、K8s 使用 CephFS CephFS是 Ceph 中基于RADOS&#xff08;可扩展分布式对象存储&#xff09;构建&#xff0c;通过将文件数据划分为对象并分布到集群中的多个存储节点上来实现高可用性和可扩展性。 首先所有 k8s 节点都需要安装 ceph-common 工具&#xff1a; yum -y ins…

C++面经(简洁版)

1. 谈谈C和C的认识 C在C的基础上添加类&#xff0c;C是一种结构化语言&#xff0c;它的重点在于数据结构和算法。C语言的设计首要考虑的是如何通过一个过程&#xff0c;对输入进行运算处理得到输出&#xff0c;而对C&#xff0c;首先要考虑的是如何构造一个对象&#xff0c;通…

PotatoPie 4.0 实验教程(41) —— FPGA实现RISC-V 扩展 GPIO UART Timer功能

TD工程介绍 我们提供的TD工程里的RISC-V核默认就开启了GPIO UART扩展&#xff0c;可以看到还有SPI和I2C扩展。因此后面的实验中TD的工程我们基本不怎么修改TD的内容&#xff0c;只需要修改TD工具中Soc_Top.v文件中的TCM0_INITFILE为FD生成的固件名称即可&#xff0c;主要修我以…

实时通讯技术 WebRTC 介绍

WebRTC WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音对话或视频对话的技术。 历史 2010年5月&#xff0c;Google以6820万美元收购VoIP软件开发商Global IP Solutions的GIPS引擎&#xff0c;并改为名为“WebRTC”。WebRTC使用…

C++ ─── 匿名对象+变量的创建顺序

目录 1. 匿名对象&#xff08;临时对象&#xff09; 2. 编译器的优化 3.变量的创建与销毁 1. 匿名对象&#xff08;临时对象&#xff09; 我们先来看有名对象的创建 Date d1; Date d2(2024,4,27);匿名对象的创建 Date(2024,56,1); 生成了一个匿名对象&#xff0c;执行完Da…

数据仓库是什么

写在前面 刚接触大数据的新手小白可能会对数据仓库这个词比较陌生&#xff0c;本文将介绍数据仓库的主要特征及OLTP&OLAP的区别&#xff0c;帮助读者更好理解数据仓库。 一、什么是数据仓库 数据仓库&#xff0c;简称数仓&#xff0c;是一个对数据进行加工&#xff0c;集…

信息系统项目管理师0073:网路集成(5信息系统工程—5.3系统集成—5.3.2网路集成)

点击查看专栏目录 文章目录 5.3.2网路集成5.3.2网路集成 计算机网络系统集成不仅涉及技术问题,而且涉及组织的管理问题,因而比较复杂,特别是大型网络系统更是如此。从技术角度讲,网络集成不仅涉及不同厂家的网络设备和管理软件,也会涉及异构和异质网络系统的互联问题。从管…

【算法学习】day1

文章目录 双指针算法移动零复写零 双指针算法 移动零 思路&#xff1a;通过定义两个下标作为双指针&#xff0c;cur从开始对整个数组进行遍历&#xff0c;而我们的dest代表的是非零元素的最后一个位置&#xff0c;cur位置为0的时候就cur&#xff0c;不为0元素的时候就交换dest…

STM32单片机C语言模块化编程实战:按键控制LED灯详解与示例

一、开发环境 硬件&#xff1a;正点原子探索者 V3 STM32F407 开发板 单片机&#xff1a;STM32F407ZGT6 Keil版本&#xff1a;5.32 STM32CubeMX版本&#xff1a;6.9.2 STM32Cube MCU Packges版本&#xff1a;STM32F4 V1.27.1 之前介绍了很多关于点灯的方法&#xff0c;比如…

设计模式学习笔记 - 项目实战一:设计实现一个支持各种算法的限流框架(实现)

概述 上篇文章&#xff0c;我们介绍了如何通过合理的设计&#xff0c;来实现框架的功能性需求的同时&#xff0c;满足易用、易扩展、灵活、低延迟、高容错等非功能性需求。在设计的过程中&#xff0c;我们也借鉴了之前讲过的一些开源项目的设计思想。比如 Spring 的低侵入松耦…

【ETAS CP AUTOSAR工具链】RTE层基本概念与开发流程

本篇文章续接上篇文章【ETAS CP AUTOSAR工具链】基本概念与开发流程&#xff0c;继续按上篇文章描述的ETAS CP工具链进行开发的基本框架&#xff0c;讲述了“RTE集成与配置”这部分的基本概念与开发流程。 RTE&#xff08;Runtime Environment&#xff09;处于应用层与基础软件…

Web前端开发 小实训(一) 成绩分类统计

用于学生web前端开发课程实训练习&#xff0c;掌握基本语法和数据类型 实训目的 使用分支语句&#xff0c;完成分数统计与等级对比,通过输入框输入分数&#xff0c;可以根据分数多少划分等级。 参考思路&#xff1a; 分析题目&#xff1a;根据输入分数进行等级划分。 操作过…