javaSE:继承

news2025/2/27 19:52:48

在谈继承之前,我们先观察下面这个代码: 

//定义一个猫类
class Cat {
    public String name;
    public int age;
    public float weigth;

    public void eat(){
        System.out.println(this.name+"正在吃饭");
    }
    public void mimi(){
        System.out.println(this.name+"正在咪咪叫");
    }
}
//定义一个狗类
class Dog {
    public String name;
    public int age;
    public float weigth;

    public void eat(){
        System.out.println(this.name+"正在吃饭");
    }
    public void bark(){
        System.out.println(this.name+"正在狗叫");
    }

}
//测试类
public class Test{
 public static void main(String[] args) {
  Dog dog=new Dog();//定义一个狗对象
  dog.name="旺财";
  dog.eat();
  dog.bark();
  Cat cat=new Cat();//定义一个猫对象
  cat.name="咪咪";
  cat.eat();
  cat.mimi();
 }
}

上面代码中发现,在猫类和狗类中,有大量代码存在重复:

 public String name;
    public int age;
    public float weigth;

    public void eat(){
        System.out.println(this.name+"正在吃饭");
    }

那能不能将这些重复的部分进行抽取呢?面向对象的思想中提出了继承的概念,专门用来进行共性抽取,实现代码复用。

继承概念:

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

例如:上面的猫类和狗类中,可以将共性进行抽取。然后采用继承的思想来达到共用。

//定义一个Animal类
class Animal(){
 public String name;
    public int age;
    public float weigth;

    public void eat(){
        System.out.println(this.name+"正在吃饭");
    }
}

继承的语法:

在猫类和狗类中继承Animal类,在java中要表示继承的关系,需要借助extends关键字,具体如下:

修饰符 class 子类 extends 父类{

}

 对猫类和狗类重新进行设计:让猫类和狗类都继承Animal类

//猫类
class Cat extends Animal{
    public void mimi(){
        System.out.println(this.name+"正在咪咪叫");
    }
}
//狗类
class Dog extends Animals{ 
    public void bark(){
        System.out.println(this.name+"正在狗叫");
    }

}

 1.子类会将父类中的成员变量或者成员方法继承到子类中了

 2.子类继承父类之后,必须要新添加自己特有的成员,体现出与父类的不同,否则就没有必要继承

父类成员访问:

1.子类中访问父类的成员变量:

1.1子类和父类不存在同名字的成员变量:
public class B {
    public int a=1;
    public int b=2;
}

public class C extends B{
    public int c=3;
    public void func(){
        System.out.println(a);//访问从父类继承下来的a
        System.out.println(b);//访问从父类继承下来的b
        System.out.println(c);//访问子类自己有的c
    }
}

在子类中也可以通过this调用来访问父类的成员变量。

public class B {
    public int a=1;
    public int b=2;
}

public class C extends B{
    public int c=3;
    public void func(){
        System.out.println(this.a);//访问从父类继承下来的a
        System.out.println(this.b);//访问从父类继承下来的b
        System.out.println(this.c);//访问子类自己有的c
    }
}

这样写代码和上面效果一样。 

1.2子类和父类存在同名的成员变量:
public class B {
    public int a=1;
    public int b=2;
}

public class C extends B{
    public int c=3;
    public int a=100;//定义一个与父类同名的成员变量
    public void func(){
        System.out.println(a);//不知道是调用哪一个a
        System.out.println(b);//访问从父类继承下来的b
        System.out.println(c);//访问子类自己有的c
    }
}

我们在子类访问变量a时,不知道调用的哪一个a,但从运行结果:来看,这里调用的a是子类自己的a。

所以当父类和子类有同名的成员变量时:优先访问子类的。

但有的人想问,如果想要先调用父类的a呢?这里就要用到一个关键字super

格式:super . 父类的成员变量

super可以用来访问子类继承过来父类的成员

具体下面会讲到。

 

 成员变量访问遵循就近原则,子类有优先访问自己的,如果没有则在父类中找。

 2.子类中访问父类的成员方法:

2.1子类和父类不存在同名的成员方法:
//父类
public class B {
   public void methodA(){
       System.out.println("父类的methodA方法...");
   }
}
//子类
public class C extends B{
    public void methodB(){
        System.out.println("子类的methodB方法...");
    }
}
//测试类
class Test {
  public static void main(String[] args) {
   C c=new C();
   c.methodA();
   c.methodB();
  }
 }

 调用成员方法与调用成员变量的操作一样。

 子类和父类成员方法没有同名的情况下,在子类方法中同对象引用访问方法时,优先调用子类自己的,若子类没有则在父类中寻找,若父类也没有则会报错

2.2子类和父类存在同名的成员方法:
2.1子类和父类存在同名的成员方法(方法里的参数不一样):
//父类
public class B {
   public void methodA(char a){
       System.out.println("父类的methodA(char a)方法...");
   }
}
//子类
public class C extends B{
    public void methodA(){
        System.out.println("子类的methodA()方法...");
    }
}
//测试类
 class Test {
  public static void main(String[] args) {
   C c=new C();
   c.methodA();
   c.methodA('a');
  }
 }

父类的methodA(char a)方法和 子类的methodA( )方法,因为方法名相同,方法参数不同。所以构成了方法的重载

根据调用的方法以及传递的参数访问合适的方法,若没有找到该方法,则会报错。

2.2子类和父类存在同名的成员方法(方法里的参数一样):
//父类
public class B {
   public void methodA(){
       System.out.println("父类的methodA()方法...");
   }
}
//子类
public class C extends B{
    public void methodA(){
        System.out.println("子类的methodA()方法...");
    }
}
//测试类
 class Test {
  public static void main(String[] args) {
   C c=new C();
   c.methodA();
  }
 }

在测试类中调用methodA的方法,默认调用的是子类的methodA的方法。

如果想调用父类的methodA的方法就要用super关键字。super.methodA()

//父类
public class B {
   public void methodA(){
       System.out.println("父类的methodA()方法...");
   }
}
//子类
public class C extends B{
    public void methodA(){
        System.out.println("子类的methodA()方法...");
    }
//通过super来调用父类的methodA的方法
 public void methoda(){
        super.methodA();
}
//测试类
 class Test {
  public static void main(String[] args) {
   C c=new C();
   c.methodA();
  }
 }

 super关键字:

有时候在一些场景下,子类和父类可能存在同名的成员变量或者成员方法,如果想从子类中访问父类中同名的成员变量或者成员方法,直接访问是无法做到的,所以Java中提供了super关键字,它主要的作用:在子类中访问父类的成员变量或者成员方法。

在子类中:

1.super.父类成员变量

2.super.父类成员方法

可以通过上面两种方式来访问父类中的成员。

super只能指向子类的父类,不能指向子类的父类的父类。

super还有第三种方法:

如果在父类中有构造方法,当子类继承父类之后,子类需要显示的调用父类的构造方法,要先帮助父类的成员进行初始化。可以用super调用父类的构造方法进而对父类进行初始化

//父类
public class B {
    public String name;
    public int age;
//父类的构造方法
    public B(String name,int age){
        this.name=name;
        this.age=age;
    }
//子类
public class C extends B{
//子类显示调用父类的构造方法
   public C(String name,int age){
       super(name,age);//
    }
}
//测试类
class Test {
  public static void main(String[] args) {
   C c=new C("酷酷的森",19);
  }
 }

在使用super的时候,要注意:super在调用父类构造方法时,一定要在方法中的第一条语句,不然会出错。

1.super调用父类的构造方法时,必须在第一行。前面我们讲过this()调用构造方法时,也只能在第一行,所以super()和this()是不能共存的。

2.当没有提供任何的构造方法的时候,java中会提供默认的构造方法,如下:

//父类
public class B {
//默认提供的构造方法
    public B(){
}
    }
//子类
public class C extends B{
/默认提供的构造方法
    public C(){
    super();
}
}

子类对象中成员是由两部分组成,父类继承下来的以及子类新增加的部分,父子父子,肯定是先有父再有子,所以在构造子类的对象时,要先调用父类的构造方法,将父类继承下来的成员初始化完整,然后调用子类的构造方法,将子类自己新增加的成员初始化完整。 

 注意:

1.在public C方法中,你也可以省略super(),因为在若父类显式定义无参或者默认的构造方法时,在子类构造方法第一行默认有隐式的super()调用。调用基类的构造方法。

2.如果父类构造方法带有参数,此时需要用户显式定义构造方法,并在子类构造方法中选用合适的父类构造方法调用,否则编译出错。

3.在子类构造方法中调用父类构造方法,super()必须在子类构造函数第一条语句

4.this()和super()不能同时出现在同一个构造方法里面。

但是只要你写了一个构造方法,这个默认构造方法就不会提供。

 super和this:

相同点:

1.都是java中的关键字

2.都只能在非静态方法中使用,用来访问非静态的成员或方法

3.在构造方法中使用时,都只能在该方法中的第一条语句,且super()和this()不能同时存在。

不同点:

1.this是指当前对象的引用, 当前对象即调用实例方法的对象。super是在子类对象中调用从父类继承下来的那部分成员的引用

2.在非静态成员方法中,this调用的是本类的方法和属性,而super用来访问从父类继承下来的方法和属性。

3. 在构造方法中:this(...)用于调用本类构造方法,super(...)用于调用父类构造方法,两种调用不能同时在构造方法中出现

4. 构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有

再谈代码块:

之前讲过静态代码块,实例代码块,构造方法在没有谈继承的时候所执行的顺序。可以在(javaSE:对象和类(2))中复习

现在讲了继承,它们又是按照什么顺序进行执行的呢?

//父类
public class B {
    public String name;
    public int age;
    //父类构造方法
    public B(String name,int age){
        this.name=name;
        this.age=age;
        System.out.println("父类构造方法执行了....");
    }
    //父类静态代码块
    static{
        System.out.println("父类静态代码块执行了....");
    }
    //父类实例代码块
    {
        System.out.println("父类实例代码块执行了....");
    }
}
//子类
public class C extends B{
    //实例代码块
    {
        System.out.println("子类实例代码块执行了.....");
    }
    //构造方法
    public C(String name,int age){
        super(name,age);
        System.out.println("子类构造方法执行了.....");
    }
    //子类静态代码块
    static{
        System.out.println("子类静态代码块执行了....");
    }
//测试类
class Test {
     public static void main(String[] args) {
         C c=new C("酷酷的森",19);
     }
 }

运行结果:

可知:先执行父类和子类的静态,再执行父类的实例和构造,最后执行子类的实例和构造

 如果改一下代码,增加一个对象,又会有什么不同呢?

//父类
public class B {
    public String name;
    public int age;
    //父类构造方法
    public B(String name,int age){
        this.name=name;
        this.age=age;
        System.out.println("父类构造方法执行了....");
    }
    //父类静态代码块
    static{
        System.out.println("父类静态代码块执行了....");
    }
    //父类实例代码块
    {
        System.out.println("父类实例代码块执行了....");
    }
}
//子类
public class C extends B{
    //实例代码块
    {
        System.out.println("子类实例代码块执行了.....");
    }
    //构造方法
    public C(String name,int age){
        super(name,age);
        System.out.println("子类构造方法执行了.....");
    }
    //子类静态代码块
    static{
        System.out.println("子类静态代码块执行了....");
    }
//测试类
 class Test {
     public static void main(String[] args) {
         C c=new C("酷酷的森",19);
         System.out.println("============");
         C cc=new C("111111",19);
     }
 }

 运行结果:

可知:第二次实例化对象,父类和子类的静态代码块都不会执行。

访问限定符:

为了实现封装特性,java引入了限定访问操作符,主要限定:类或者类中的成员能否在类外或者其他包中使用。

 private修饰的成员,只能在当前类访问

default修饰的成员,只能在同一个包低下的类中访问

public修饰的成员,公共的,任何地方都能使用

protected修饰的成员,同一个包低下可以使用,但是不同包下,只有子类才能使用。

 继承方式:

1.单继承:

public class A{
....
}
public B extends A{
....
}

2.多层继承:

public class A{
....
}
public class B extends A{
....
}
public class C extends B{
....
}

但是多继承,也不能无限继承下去。一般不超过3层的继承关系

3.不同类继承同一个类:

public class A{
....
}
public class B extends A{
....
}
public class C extends A{
....
}

4.java是不支持多继承的:一个类继承有多个父类是不允许的

java不支持多继承,但是可以通过接口的修形式,支持多继承

 final关键字:

1.final 关键可以用来修饰变量、成员方法以及类。
2.final修饰的变量是常量,此时这个变量的值就不能被修改了

3.如果一个类不想被其他类继承,此时可以用关键字final来,修饰这个类,此时这个类就叫密封类,不允许被其他类继承。

4.final修饰方法,这个方法就不能被重写。

继承和组合:

组合和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。

继承是is-a的关系:比如:猫是动物,狗也是动物

组合是has-a的关系或者是 a part of (一部分)的关系:比如:汽车有发动机,轮子还有车载系统。

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

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

相关文章

校园环境气象实时监测系统

随着物联网技术的发展越来越成熟,它不断地与人们的日常生活和工作深入融合,推动着社会的进步。其中物联网系统集成在高校实践课程中可以应用到许多项目,如环境气象检测、花卉种植信息化监管、水质信息化监管、校园设施物联网信息化改造、停车…

经常混淆的ADC输入类型!

大家好,这里是大话硬件。 这篇文章我们来聊聊ADC的输入类型。 ADC的输入类型根据ADI的官网,分为了3种类型,单端,差分,伪差分。如下图快速选型的界面所示。 同时,TI的官网对ADC的输入类型划分也是同样的3种类型。 可见,两个器件厂家对ADC的输入类型都是这样定义的。 …

FPGA早鸟课程第二弹 | Vivado 设计静态时序分析和实际约束

在FPGA设计领域,时序约束和静态时序分析是提升系统性能和稳定性的关键。社区推出的「Vivado 设计静态时序分析和实际约束」课程,旨在帮助工程师们掌握先进的设计技术,优化设计流程,提高开发效率。 课程介绍 关于课程 权威认证&…

目标检测——YOLOv10算法解读

论文:YOLOv10: Real-Time End-to-End Object Detection (2024.5.23) 作者:Ao Wang, Hui Chen, Lihao Liu, Kai Chen, Zijia Lin, Jungong Han, Guiguang Ding 链接:https://arxiv.org/abs/2405.14458 代码:https://github.com/THU…

Kimichat使用案例019:15个Kimichat提示词案例

文章目录 一、扮演招聘经理二、扮演英语教师三、文章修改润色四、模仿特定作者写文章五、扮演任何一个角色六、像董宇辉一样介绍一本书七、写商业计划书的大纲八、头脑风暴九、总结文章十、推荐书籍十一、写电子邮件十二、学习Python编程十三、Python编程十四、制作菜谱十五、写…

【Python/Pytorch 】-- 滑动窗口算法

文章目录 文章目录 00 写在前面01 基于Python版本的滑动窗口代码02 算法效果 00 写在前面 写这个算法原因是:训练了一个时序网络,该网络模型的时序维度为32,而测试数据的时序维度为90。因此需要采用滑动窗口的方法,生成一系列32…

一种稀疏贝叶斯学习的旋转机械故障诊断方法(MATLAB)

轴承的故障诊断技术是通过检测轴承故障特征信息来判断轴承的具体故障为位置或损伤程度。在轴承发生损坏时,故障特征信息会随着工作时间的增长变得明显。轴承的损坏过程可以分为四个阶段。第一个阶段为损伤初始阶段,轴承故障特征信号一般无法测量。第二个…

一种基于非线性滤波过程的旋转机械故障诊断方法(MATLAB)

在众多的旋转机械故障诊断方法中,包络分析,又称为共振解调技术,是目前应用最为成功的方法之一。首先,对激励引起的共振频带进行带通滤波,然后对滤波信号进行包络谱分析,通过识别包络谱中的故障相关的特征频…

【昇思25天学习打卡营打卡指南-第一天】基本介绍与快速入门

昇思MindSpore介绍 昇思MindSpore是一个全场景深度学习框架,旨在实现易开发、高效执行、全场景统一部署三大目标。 其中,易开发表现为API友好、调试难度低;高效执行包括计算效率、数据预处理效率和分布式训练效率;全场景则指框架…

【windows|004】BIOS 介绍及不同品牌电脑和服务器进入BIOS设置的方法

🍁博主简介: 🏅云计算领域优质创作者 🏅2022年CSDN新星计划python赛道第一名 🏅2022年CSDN原力计划优质作者 ​ 🏅阿里云ACE认证高级工程师 ​ 🏅阿里云开发者社区专家博主 💊交流社…

使用 CloudFlare 的站长们注意了

最近 CloudFlare 改版升级比较频繁,除了 CloudFlare 后台布局有多处调整外,还包括部分模块弃用的调整,所以明月建议在使用 CloudFlare 的站长们及时跟进调整设置,否则可能会影响网站的加速和安全防护能力的,严重点儿甚至会造成部分网站功能性错误影响用户体验。 尤其要重视…

Java面试八股之myBatis的优缺点

myBatis的优缺点 优点: 灵活性高: MyBatis允许直接编写原生SQL语句,这意味着你可以针对特定的数据库特性进行优化,处理复杂的查询逻辑,从而更好地满足业务需求。 易于上手: 相比Hibernate等其他ORM工具&…

跨越金融服务门槛,智慧银行推动普惠金融全面升级

在数字化浪潮的推动下,金融服务正经历着一场前所未有的变革。智慧银行,作为这场变革的领航者,以其独特的技术优势和创新思维,正在逐步打破传统金融服务的局限,推动普惠金融的全面升级。本文将深入探讨智慧银行如何通过…

Socket 原理和思考

众所周知Reactor是一种非常重要和应用广泛的网络编程模式,而Java NIO是Reactor模式的一个具体实现,在Netty和Redis都有对其的运用。而不管上层模式如何,底层都是走的Socket,对底层原理的了解会反哺于上层,避免空中楼阁…

npm install 安装不成功,node-sass缺失,提示python环境缺失的解决办法

npm install 安装不成功的原因 是因为缺少python的环境 解决方法: 1、去官网下载 https://www.python.org/downloads/release,注意安装3.6版本以上还是会有问题,建议安装3.6版本以上的,我选择安装的是3.9.6,对应的下载…

Git pull下来时合并分支

执行git pull时报错如下 解决方法&#xff1a; VSCode git中手动选取分支&#xff0c;完成合并 这一步&#xff0c;也可以在README.md中进行Tutorial&#xff0c; 上面出现冲突后&#xff0c;README.md会被更改成下述形式&#xff0c; If you have questions, please <…

支持 MKV、MP4、AVI、MPG 等格式视频转码器

一、简介 1、一款开源的视频转码器&#xff0c;适用于 Linux、Mac 和 Windows。它是一个免费的工具&#xff0c;由志愿者们开发&#xff0c;可以将几乎所有格式的视频转换为现代、广泛支持的编码格式。你可以在官网上下载该应用或源代码。该软件支持 MKV、MP4、AVI、MPG 等格式…

[Linux] 系统管理

全局配置文件 用户个性化配置 配置文件的种类 alias命令和unalias命令 进程管理 进程表

SAP PP学习笔记22 - 生产订单(制造指图)的元素1

前面几章讲了PP 里面生产计划的各种策略以及策略的Customize。 SAP PP学习笔记20 - 复习总结一下MTS&#xff0c;MTO&#xff0c;ATO的各种生产策略-CSDN博客 SAP PP学习笔记21 - 计划策略的Customize&#xff1a;策略组 &#xff1e; 策略 &#xff1e; 需求类型 &#xff1…

windows系统中开发的GO程序生成docker镜像并部署到阿里云服务(linux系统)的操作说明

本文简述将go程序生成docker镜像的操作方法&#xff0c;以及如何部署到阿里云服务。其中go程序在windows系统中开发&#xff0c;阿里云服务的操作系统为linux&#xff08;centos7.9&#xff09;&#xff0c;以下为流程示意图&#xff1a; 一、window系统中开发go程序 程序实现…