Java中继承详解

2023-11-09

为什么要继承?

面相对象思想中提出了继承的概念,专门用来进行共性抽取,实现代码复用。

继承概念

子类将父类的一些属性与方法继承过来,然后自己再添加一些新的特性。

继承的语法

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

2:继承的是:除了父类的构造方法外的所有。

3:单继承:一个子类只能继承一个父类,不可能继承2个或多个类。

4: 子类继承父类中的除构造方法外的所有东西,但是父类中的private修饰的方法和字段,
在子类中是无法被访问的。

public class Dog extends Animal{
void bark(){
System.out.println(name + "汪汪汪~~~");
}
}

父类成员访问

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

1.子类和父类不存在同名成员变量
public class Base {
int a;
int b;
}
public class Derived extends Base{
int c;
public void method(){
a = 10; // 访问从父类中继承下来的a
b = 20; // 访问从父类中继承下来的b
c = 30; // 访问子类自己的c
}
}
2:子类和父类成员变量同名
public class Base {
int a;
int b;
int c;
}
/
public class Derived extends Base{
int a; // 与父类中成员a同名,且类型相同
char b; // 与父类中成员b同名,但类型不同
public void method(){
a = 100; // 访问父类继承的a,还是子类自己新增的a?
b = 101; // 访问父类继承的b,还是子类自己新增的b?
c = 102; // 子类没有c,访问的肯定是从父类继承下来的c
}
}

在子类方法中 或者 通过子类对象访问成员时

如果访问的成员变量子类中有,优先访问自己的成员变量

如果访问的成员变量与父类中成员变量同名,则优先访问自己的.

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

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

1:成员方法名字不同
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
}
public class Derived extends Base{
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
methodB(); // 访问子类自己的methodB()
methodA(); // 访问父类继承的methodA()
}
}

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

2:成员方法名字相同
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
public 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 关键字的引入

子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成 员时,该如何操作?直接访

问是无法做到的,Java提供了super关键字,该关键字主要作用:在子类方法中访问父 类的成员(字段和方法)。

public class Base {
int a;
int b;
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
public class Derived extends Base{
int a; // 与父类中成员变量同名且类型相同
char b; // 与父类中成员变量同名但类型不同
// 与父类中methodA()构成重载
public void methodA(int a) {
System.out.println("Derived中的method()方法");
}
// 与基类中methodB()构成重写(即原型一致,重写后序详细介绍)
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
// 对于同名的成员变量,直接访问时,访问的都是子类的
a = 100; // 等价于: this.a = 100;
b = 101; // 等价于: this.b = 101;
// 注意:this是当前对象的引用
// 访问父类的成员变量时,需要借助super关键字
// super是获取到子类对象中从基类继承下来的部分
super.a = 200;
super.b = 201;
// 父类和子类中构成重载的方法,直接可以通过参数列表区分清访问父类还是子类方法
methodA(); // 没有传参,访问父类中的methodA()
methodA(20); // 传递int参数,访问子类中的methodA(int)
// 如果在子类中要访问重写的基类方法,则需要借助super关键字
methodB(); // 直接访问,则永远访问到的都是子类中的methodA(),基类的无法访问到
super.methodB(); // 访问基类的methodB()
}
}

注意:

1:只能在非静态方法中使用

2: 在子类方法中,访问父类的成员变量和方法。

子类构造方法

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

public class Base {
public Base(){
System.out.println("Base()");
}
}
public class Derived extends Base{
public Derived(){
// super(); // 注意子类构造方法中默认会调用基类的无参构造方法:super(),
// 用户没有写时,编译器会自动添加,而且super()必须是子类构造方法中第一条语句,
// 并且只能出现一次
System.out.println("Derived()");
}
}
public class Test {
public static void main(String[] args) {
Derived d = new Derived();
}
}
结果打印:
Base()
Derived()

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

注意:

1: 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构 造方法。

2: 如果父类构造方法是带有参数的,此时编译器不会再给子类生成默认的构造方法,此时需要用户为子类显式 定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。//实践

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

4: super(…)只能在子类构造方法中出现一次,并且不能和this同时出现

super和this

在这里插入图片描述

相同点:

1: 只能在类的非静态方法中使用,用来访问非静态成员方法和字段

2: 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在

不同点:

1: this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用

2:在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性

3: this是非静态成员方法的一个隐藏参数,super不是隐藏的参数

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

protected 关键字

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

在这里插入图片描述

// 为了掩饰基类中不同访问权限在子类中的可见性,为了简单类B中就不设置成员方法了
// extend01包中
public class B {
private int a;
protected int b;
public int c;
int d;
}
// extend01包中
// 同一个包中的子类
public class D extends B{
public void method(){
// super.a = 10; // 编译报错,父类private成员在相同包子类中不可见
super.b = 20; // 父类中protected成员在相同包子类中可以直接访问
super.c = 30; // 父类中public成员在相同包子类中可以直接访问
super.d = 40; // 父类中默认访问权限修饰的成员在相同包子类中可以直接访问
}
}
// extend02包中
// 不同包中的子类
public class C extends B {
public void method(){
// super.a = 10; // 编译报错,父类中private成员在不同包子类中不可见
super.b = 20; // 父类中protected修饰的成员在不同包子类中可以直接访问
super.c = 30; // 父类中public修饰的成员在不同包子类中可以直接访问
//super.d = 40; // 父类中默认访问权限修饰的成员在不同包子类中不能直接访问
}
}
// extend02包中
// 不同包中的类
public class TestC {
public static void main(String[] args) {
C c = new C();
c.method();
// System.out.println(c.a); // 编译报错,父类中private成员在不同包其他类中不可见
// System.out.println(c.b); // 父类中protected成员在不同包其他类中不能直接访问
System.out.println(c.c); // 父类中public成员在不同包其他类中可以直接访问
// System.out.println(c.d); // 父类中默认访问权限修饰的成员在不同包其他类中不能直接访问
}
}

注意:

1: Test C 是一个普通的类,不是子类,也不是父类。

2: j a v a中有很多的类,每个类中又有2个东西:字段(成员变量)和方法。

字段:不是方法的都是字段。

3:方法(不管是不是静态的方法)里面可以创建对象,方法里面可以干大多数想干的事。

4:如果没有加访问修饰限定符,那默认的是包访问权限,只能在同一个包中进行访问。

举一反三

class anmail{
    public String name;
    public int age;
    public void jihe(){
        System.out.println(this.name+" "+this.age+" "+"eat!");
    }
    public anmail(String name){
        this.name=name;

    }
    public anmail(int age){
        this.age=age;
    }
}

class dog extends anmail {
    
    public int a;

    public dog(int a){
        super(a);//相当与anmail(a)
    }
    /*
    重点:
    public dog(int a){
        super(this.a);
        //因为本类当中的a还没有初始化。
    }
    这样写是错误的。
    例子看下面的图片
    */

    public void func(int x) {
        this.a = x;
    }
}

public class Text15 {
    public static void main(String[] args) {
        bird bird1=new bird("鸟");
        bird1.age=12;
        dog dog1=new dog(10);
        dog1.func(10);
        dog1.name="牛仔";
        bird1.jihe() ;
        dog1.jihe();
    }
}

在这里插入图片描述

执行逻辑:

编译器通过public找到Z类;然后找到Z类中的main方法;然后创建了一个Z对象,然后调用Z的构造方法;

从而进入Z的构造方法,因为Z继承了X ,所以Z是X的子类,所以要先进行构造父类,

其实public Z(super())里面有一个隐藏的super

{

}

现在要进行构造父类X,在进行X构造的时候,先构造(初始化)X的成员变量,再构造(初始化)X的代码块,最后构造(初始化)X的构造方法。

所以先进行y对象的创建,然后调用Y的构造方法;同样在进行Y构造的时候,先构造(初始化)Y的成员变量,再构造(初始化)Y的代码块,最后构造(初始化)Y的构造方法。

所以打印Y后回到类X打印X,回到Z的构造方法,同样在进行Z构造的时候,先构造(初始化)Z的成员变量,再构造(初始化)Z的代码块,最后构造(初始化)Z的构造方法。所以先打印Y再打印Z。

即打印:YXYZ

理解同一个包中的不同类:–>

在这里插入图片描述

理解private:

在这里插入图片描述
在这里插入图片描述

private 修饰的成员,只能被在同一个包中,同一个类下创建的对象访问。
//例如:在Animal类中有一个private修饰的成员,其只能在Animal类中创建的以Animal为模板的对象中访问。
1:一个包中有很多的类,编译器会自动的从public修饰的类中寻找main方法,如果没有找到的话就去其他的类寻找。
2:类的方法中只能调用其他方法,不可以声明实例一个方法
3:main方法是一个static修饰的方法,他不可以访问非静态的方法与变量
4:在方法里面可以创建一个对象,在方法外面类里面也可以创建一个对象。
5:在静态的方法中,访问非静态的变量和方法时,需要对象的引用。
    
    例如:
    
    public class Shut extends Animal {
    public  static void method(Shut shut1){
        System.out.println(shut1.name);//对象的引用
    }
    public static void main(String[] args) {

        Shut shut1=new Shut();
        method(shut1);
        shut1.name="111";
        shut1.age=10;

    }
}

对protected 中“可以访问不同包中的子类”的进一步理解

在这里插入图片描述
在这里插入图片描述

继承的方式:

一般我们不希望出现超过三层的继承关系

如果想从语法上进行限制继承, 就可以使用 final 关键字

   shut1.name="111";
    shut1.age=10;

}

一般我们不希望出现超过三层的继承关系

如果想从语法上进行限制继承, 就可以使用 final 关键字

少年的肩应该担起草长莺飞和清风明月, 女孩的眼应该藏下星辰大海和万丈光芒。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java中继承详解 的相关文章

随机推荐

  • 动态数据锚点定位

    锚点定位 左侧点击右侧锚点定位样式一 div class left a href book time a a href search a a href search flow a div div class right div div di
  • Java算法LC刷(3.无重复字符的最长子串)

    无重复字符的最长子串 package com core doc LeetCode public class T3 public static void main String args int map lengthOfLongestSubs
  • DeprecationWarning: find_element_by_* commands are deprecated. Please use find_element() instead

    问题描述 使用find element by id时报错 DeprecationWarning find element by commands are deprecated Please use find element instead
  • php组件缓冲区溢出漏洞,一个缓冲区溢出漏洞的简易教程

    这篇文章类似于 傻瓜系列之利用缓冲区溢出 在这类漏洞中 我们的做法是利用网络 程序控制器 输入等等 发送超大的数据缓冲区给程序 覆盖程序内存的重要部分 在这些缓冲区覆盖程序内存之后 我们可以重定向程序的执行流并运行注入代码 首先 我们需要做
  • 财务用计算机在成本核销,《初级会计电算化》精选题库附答案解析(五)

    初级会计电算化 练习题五 含答案解析 1 当月的记账凭证必须全部记账 如有未记账的当月凭证 系统将 TopSage A 不能结账 B 继续结账 C 放到下月 答案 A 2 往来账管理的往来客户档案的设置其最主要内容是 TopSage A 客
  • 关于 IDEA创建Spring项目时出现Cannot resolve plugin XXX的解决办法

    在创建spring项目时候Plugins文件夹下面出现许多的红色波浪报错 如下 org apache maven plugins maven clean plugin 2 5 org apache maven plugins maven c
  • 前端 - js - 编程题23 - 两数之和

    给定一个整数数组 nums 和一个目标值 target 请你在该数组中找出和为目标值的那 两个 整数 并返回他们的数组下标 你可以假设每种输入只会对应一个答案 但是 你不能重复利用这个数组中同样的元素 示例 给定nums 2 7 11 15
  • Windows系统如何查看占用的端口

    Windows系统如何查看占用的端口 在有些时候 我们需要知道Windows系统占用了那些端口 比如 需要在服务器上部署一个应用程序时 需要给这个应用程序提供空闲端口用来通信 除了一些约定俗成的端口外 例如 HTTP服务占用80端口 FTP
  • Java多线程列子

    问题如下 两个线程 线程A 线程B 一个固定容量为50的队列List
  • 解决Spring boot 工程console打印太多信息

    resources下添加配置文件 logback xml 添加下面代码
  • 决策树(Decision Tree)

    一 简介 决策树 decision tree 是一种基本的分类与回归方法 本章主要讨论用于分类的决策树 决策树模型呈树形结构 在分类问题中 表示基于特征对实例进行分类的过程 它可以认为是if then规则的集合 也可以认为是定义在特征空间与
  • SpringBoot实战——个人博客项目

    目录 一 项目简介 二 项目整体架构 数据库模块 后端模块 前端模块 三 项目具体展示 四 项目的具体实现 1 一些准备工作 数据库 数据表的创建 设置数据库和MyBatis的配置 将前端项目引入到当前项目中 2 登录注册模块 实体类的创建
  • 【手写一个Tomcat】SimpleTomcat-01

    目录 前言 实现 http TomcatRequest http TomcatResponse http TomcatServlet SimpleTomcat servlet FirstServlet servlet SecondServl
  • 常用数据库validationQuery检查语句

    validationQuery是用来验证数据库连接的查询语句 这个查询语句必须是至少返回一条结果的SELECT语句 每种数据库都有各自的验证语句 下表中从网上收集了几种常见数据库的validationQuery 数据库 validation
  • 搭建服务注册与发现中心

    使 Spring Cloud Netflix 中的 Eureka 搭建服务注册与发现中 创建SpringBoot应 添加依赖 spring web eureka server 配置服务注册与发现中心 设置服务注册与发现中 的端 server
  • 数据挖掘应用实例_手把手教你做数据挖掘 !(附教程&数据源)

    作者 宋莹 本文长度为10427字 建议阅读20 分钟 本文为你介绍数据挖掘的知识及应用 引言最近笔者学到了一个新词 叫做 认知折叠 就是将复杂的事物包装成最简单的样子 让大家不用关心里面的细节就能方便使用 作为数据科学领域从业者 我们所做
  • 行业首发!《硬件工程师进阶武器库》免费赠送!限量2000份,送完不补!

    对于刚入硬件行业的3 5年工程师来说 如果能有一个好的师傅引路 那是最好不过的了 但是往往大神很少 能够愿意倾囊相授的也难遇到 如果在这个阶段 能够找到行业中top级企业内部的学习资料 或者高阶的技能图谱 或者行业大神的学习教程等等 就能够
  • Unity Koreographer 之 音乐制作插件介绍学习,一般使用步骤介绍(包括:一般音乐游戏制作流程简绍) 一

    Unity Koreographer 之 音乐制作插件介绍学习 一般使用步骤 介绍 一 目录 Unity Koreographer 之 音乐制作插件介绍学习 一般使用步骤 一 一 Koreographer 简单介绍 二 Koreograph
  • 例说数据结构&STL(一)——vector

    1 白话vector 向量 数据结构vector又称为动态数组 因为它无需像普通数组定义的时候规定具体空间大小 一定程度上可以节约内存空间 但是它又具有普通数组连续物理内存存储的优势 即各元素之间构成一个线性的前后次序 数据的物理存储位置与
  • Java中继承详解

    为什么要继承 面相对象思想中提出了继承的概念 专门用来进行共性抽取 实现代码复用 继承概念 子类将父类的一些属性与方法继承过来 然后自己再添加一些新的特性 继承的语法 1 在Java中如果要表示类之间的继承关系 需要借助extends关键字