Java中的继承

文章目录

  • 前言
  • 一、为什么需要继承
  • 二、继承的概念
  • 三、继承的语法
  • 四、父类成员访问
    • 4.1子类中访问父类的成员变量
      • 1.子类和父类不存在同名成员变量
      • 2.子类和父类成员变量同名
    • 4.2子类中访问父类的成员方法
      • 1.成员方法名字不同
      • 2.成员方法,名字相同
  • 五、super和this关键字
  • 六、子类构造方法
  • 七、代码块的执行顺序
  • 八、继承方式
  • 九、final关键字
  • 十、继承和组合


前言

在前面的学习中我们已经讲解了面向对象的三大特性中的封装,接下来我们再来讲解三大特性中的继承


一、为什么需要继承

class Dog {String name;int age;String color;public void eat() {System.out.println("正在吃");}public void bark() {System.out.println("正在汪汪叫");}
}
class Cat {String name;int age;public void eat() {System.out.println("正在吃");}public void sleep() {System.out.println("正在睡觉");}
}

通过观察以上代码,我们发现在狗和猫这两个类中我们定义了一些重复的代码,那么我们就可以使用继承来进行共性的抽取,实现代码的复用

二、继承的概念

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

三、继承的语法

在Java中如果要表示类之间的继承关系,需要借助extends关键字

修饰符 class 子类 extends 父类 {
// ...
}

子类也可以叫做派生类,父类也可以叫做基类和超类
用继承重新设计狗和猫这两个类

class Animal {String name;int age;public void eat() {System.out.println(this.name+"正在吃");}
}
class Dog extends Animal {String color;public void bark() {System.out.println(this.name+"正在汪汪叫");}
}
class Cat extends Animal {public void sleep() {System.out.println(this.name+"正在睡觉");}
}
public class Test {public static void main(String[] args) {Dog dog = new Dog();//dog类中并没有定义name和age,name和age属性肯定是从父类Animal中继承下来的System.out.println("名字:"+dog.name+" 年龄:"+dog.age+" 颜色:"+dog.color);//eat方法也是从父类Animal中继承下来的dog.eat();dog.bark();Cat cat = new Cat();//cat类中也没有定义任何成员变量,name和age属性肯定是从父类Animal中继承下来的System.out.println("名字:"+cat.name+" 年龄:"+cat.age);//这里的eat方法也是从父类Animal中继承下来的cat.eat();cat.sleep();}
}

注意:
1.子类会将父类中的成员变量或者成员方法继承到子类中了
2.子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了

四、父类成员访问

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

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

class Base {int a;int b;
}
class Derived extends Base{int c;public void fend(){a = 5; // 访问从父类中继承下来的ab = 10; // 访问从父类中继承下来的bc = 15; // 访问子类自己的c}
}

2.子类和父类成员变量同名

class Base {int a;int b;int c;
}
class Derived extends Base{int a; // 与父类中成员a同名,且类型相同char b; // 与父类中成员b同名,但类型不同public void method(){a = 100; // 访问子类新增的ab = 101; // 访问子类新增的bc = 102; // 子类没有c,访问的肯定是从父类继承下来的c// d = 103; // 编译失败,因为父类和子类都没有定义成员变量b}
}

在子类方法中 或者 通过子类对象访问成员时:
1.如果访问的成员变量子类中有,优先访问自己的成员变量
2.如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错
3.如果访问的成员变量与父类中成员变量同名,则优先访问自己的
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找

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

1.成员方法名字不同

class Base {public void methodA(){System.out.println("Base中的methodA()");}
}
class Derived extends Base {public void methodB() {System.out.println("Derived中的methodB()方法");}public void methodC(){methodB(); // 访问子类自己的methodB()methodA(); // 访问父类继承的methodA()// methodD(); // 编译失败,在整个继承体系中没有发现方法methodD()}
}

总结:成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错

2.成员方法,名字相同

class Base {public void methodA(){System.out.println("Base中的methodA()");}public void methodB(){System.out.println("Base中的methodB()");}
}
class Derived extends Base{public void methodA(int a) {System.out.println("Derived中的method(int)方法");}public void methodB(){System.out.println("Derived中的methodB()方法");}public void methodC(){methodA(); // 没有传参,访问父类中的methodA()methodA(20); // 传递int参数,访问子类中的methodA(int)methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),基类的无法访问到}
}

说明:
1.通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
2.通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错;

五、super和this关键字

super关键字,该关键字主要作用:在子类方法中访问父类的成员

class Base {public int a = 1;public int b = 2;
}
class Derived extends Base {public int a = 10;public int c = 20;public void print() {System.out.println(super.a);System.out.println(this.a);System.out.println(this.b);System.out.println(super.b);System.out.println(this.c);}
}
public class Test {public static void main(String[] args) {Derived derived = new Derived();derived.print();}
}

在这里插入图片描述
在这里插入图片描述
优先访问子类的,子类没有再访问父类
在这里插入图片描述
注意:
1.只能在非静态方法中使用
2.在子类方法中,访问父类的成员变量和方法
相同点:
1.都是Java中的关键字
2.只能在类的非静态方法中使用,用来访问非静态成员方法和字段
3.在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
不同点:
1.this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用
2.在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
3.在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造方法中出现
4.构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有

六、子类构造方法

父子父子,先有父再有子,即:子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法

class Base {public Base() {System.out.println("Base::test()");}
}
class Derived extends Base {public Derived() {System.out.println("Derived::test()");}
}
public class Test {public static void main(String[] args) {Derived derived = new Derived();}
}

在这里插入图片描述
在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执行子类的构造方法,因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整
注意:
1.若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法
2.如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
3.在子类构造方法中,super(…)调用父类构造时,必须是子类构造函数中第一条语句。
4.super(…)只能在子类构造方法中出现一次,并且不能和this同时出现

七、代码块的执行顺序

在没有继承关系时的执行顺序

class Person {public Person() {System.out.println("构造方法");}static {System.out.println("静态方法");}{System.out.println("实例方法");}
}
public class Test {public static void main(String[] args) {Person person1 = new Person();System.out.println("********");Person person2 = new Person();}
}

在这里插入图片描述
1.静态代码块先执行,并且只执行一次,在类加载阶段执行
2.当有对象创建时,才会执行实例代码块,实例代码块执行完成后,最后构造方法执行
有继承关系时的执行顺序

class Person {public Person() {System.out.println("Person:构造方法");}static {System.out.println("Person:静态方法");}{System.out.println("Person:实例方法");}
}
class Student extends Person {public Student() {System.out.println("Student:构造方法");}static {System.out.println("Student:静态方法");}{System.out.println("Student:实例方法");}
}
public class Test {public static void main(String[] args) {Student student1 = new Student();System.out.println("********");Student student2 = new Student();}
}    

在这里插入图片描述
结论如下:
1、父类静态代码块优先于子类静态代码块执行,且是最早执行
2、父类实例代码块和父类构造方法紧接着执行
3、子类的实例代码块和子类构造方法紧接着再执行
4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

八、继承方式

在Java中支持以下几种继承方式:
单继承

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

多层继承

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

不同类继承同一个类

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

注意:Java中不支持多继承
时刻牢记, 我们写的类是现实事物的抽象. 而我们真正在公司中所遇到的项目往往业务比较复杂, 可能会涉及到一系列复杂的概念, 都需要我们使用代码来表示, 所以我们真实项目中所写的类也会有很多. 类之间的关系也会更加复杂.
但是即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了.
如果想从语法上进行限制继承, 就可以使用 final 关键字

九、final关键字

final关键可以用来修饰变量、成员方法以及类
1.修饰变量或字段,表示常量(即不能修改)
2.修饰类:表示此类不能被继承
String字符串类,就是用final修饰的,不能被继承
3.修饰方法:表示该方法不能被重写(后序介绍)

十、继承和组合

和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。简单说组合其实是一种思想
继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物
组合表示对象之间是has-a的关系,比如:汽车

class Tire{
// ...
} /
/ 发动机类
class Engine{
// ...
} /
/ 车载系统类
class VehicleSystem{
// ...
}
class Car{private Tire tire; // 可以复用轮胎中的属性和方法private Engine engine; // 可以复用发动机中的属性和方法private VehicleSystem vs; // 可以复用车载系统中的属性和方法// ...
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

很多工程师,最后都是被生活裹挟,没法一直在技术路径走到极致

最近比较少更了,但内容一直在写,只是从长文变成了短文,直接发朋友圈了。 如果喜欢我写的内容,请移步到朋友圈。 我是一个不喜欢讲哲理的人,感觉哲学都是理论,都是鸡血,很难落地,我…

有效数字(表示数值的字符串),剑指offer,力扣

目录 题目地址: 我们直接看题解吧: 难度分析: 解题方法: 审题目事例提示: 解题思路: 代码实现: 题目地址: LCR 138. 有效数字 - 力扣(LeetCode) 难度&#xf…

MySQL 分库分表与 TiDB(平凯数据库),如何选择?

随着互联网行业的飞速发展,数据量不断增长,传统的关系型数据库已经无法满足大规模数据处理的需求。为了解决这一问题,分库分表和分布式数据库应运而生。本文将对比分析 MySQL 分库分表和 TiDB 这两种解决方案,帮助大家更好地选择适…

【VSCode】Visual Studio Code 配置简体中文环境教程

介绍 Visual Studio Code(简称 VS Code)是一款轻量级的代码编辑器,它支持多种编程语言,并且具有丰富的功能和插件扩展。如果你更喜欢使用简体中文界面,那么本教程将向你展示如何在 VS Code 中配置简体中文环境。 步骤…

Redhat8.3上部署Lustre文件系统

Lustre文件系统 Lustre架构是用于集群的存储架构。Lustre架构的核心组件是Lustre文件系统,它在Linux操作系统上得到支持,并提供了一个符合POSIX *标准的UNIX文件系统接口。 Lustre存储架构用于许多不同类型的集群。它以支持世界上许多最大的拥有数万个…

ubuntu22.04下hadoop3.3.6+hbase2.5.6+phoenix5.1.3开发环境搭建

一、涉及软件包资源清单 1、java 这里使用的是openjdk 2、hadoop-3.3.6.tar.gz 3、hbase-2.5.6-hadoop3-bin.tar.gz 4、phoenix-hbase-2.5-5.13-bin.tar.gz 5、apache-zookeeper-3.8.3-bin.tar.gz 6、openssl-3.0.12.tar.gz 二、安装 1、操作系统环境准备 换源 sudo vim /et…

uniapp基础学习笔记01

文章目录 本博客根据黑马教程学习uniapp一、技术架构二、创建项目2.1 Hbuilder创建2.2 插件安装2.3 微信开发者工具配置与运行2.3.1 简单修改基础页面 2.4 pages.json和tabBar2.4.1 pages.json与tabBar配置2.4.2 案例 三、uniapp与原生开发的区别 本博客根据黑马教程学习uniapp…

推出链上美债产品的 ProsperEx:RWA 衍生品赛道的早期玩家

美债是目前 RWA 市场中进展较快的领域之一,目前该市场的规模(TVL)已经达到了 $770 M,并且美债 RWA 市场目前正在以每月大约 10% 的增长速度扩大规模。 图源:app.rwa.xyz/treasuries 在该领域,固定收益类美债…

继承、多态

复习 需求: 编写一个抽象类:职员Employee,其中定义showSalary(int s)抽象方法;编写Employee的子类,分别是销售员Sales和经理Manager,分别在子类中实现对父类抽象方法的重写,并编写测试类Test查看输出结果 package cn.…

VulnHub Prime_Series_Level-1

一、信息收集 1.nmap扫描 ┌──(root💀kali)-[~/桌面] └─# arp-scan -l┌──(root💀kali)-[~/桌面] └─# nmap -sS -A -p- 192.168.103.202发现开放了22和80端口 2.web页面 打开80端口的web页面,是一张静态的图片,没什么价…

Mybatis-Plus条件构造器QueryWrapper

Mybatis-Plus条件构造器QueryWrapper 1、条件构造器关系介绍 介绍 : 上图绿色框为抽象类 蓝色框为正常类,可创建对象 黄色箭头指向为父子类关系,箭头指向为父类 wapper介绍 : Wrapper : 条件构造抽象类&#xff0…

ctfshow 文件上传 151-161

文件上传也好久没做了。。 手很生了 151 前端绕过 只能上传png文件 使用bp抓包,修改文件名后缀为php 上传成功,发现文件上传路径 使用蚁剑连接 找到flag 152 152 后端校验 跟上一关一样 表示后面即使执行错误,也不报错 抓包修改文件…