零基础 “入坑” Java--- 十、继承

文章目录

  • 一、何为继承
  • 二、继承语法
  • 三、父类成员访问
    • 1.成员变量
    • 2.成员方法
  • 四、super关键字
  • 五、子类构造方法
  • 六、super和this辨析
  • 七、再谈初始化
  • 八、protected关键字
  • 九、继承方式
  • 十、final关键字
  • 十一、继承与组合

根据我们学过的类的知识,我们来定义两个类:一个猫类,一个狗类:

class Dog {public String name;public int age;public String sex;public void eat() {System.out.println(this.name + "吃饭");}public void sleep() {System.out.println(this.name + "睡觉");}public void wang() {System.out.println(this.name + "汪汪叫");}
}
class Cat {public String name;public int age;public String sex;public void eat() {System.out.println(this.name + "吃饭");}public void sleep() {System.out.println(this.name + "睡觉");}public void miao() {System.out.println(this.name + "喵喵叫");}
}

仔细观察代码会发现,两个类中存在许多共性,代码就会比较冗余。为了解决这个问题,面向对象思想中提出了继承的概念,用于对共性进行抽取,实现代码复用,减少冗余。

一、何为继承

继承是面向对象思想中可以实现代码复用的一种重要手段,它允许程序员在保持原有类(父类/基类/超类) 的基础上进行扩展,增添新功能,由此产生的新的类,称为子类/派生类。

继承主要解决:对共性进行抽取,从而实现代码的复用。

二、继承语法

在Java中借助extends关键字实现继承关系,语法格式为:

修饰符 class 子类 extends 父类 {
//语句
}

我们根据语法对猫和狗类的共性进行抽取:

class Animal {public String name;public int age;public String sex;public void eat() {System.out.println(name + "吃饭");}public void sleep() {System.out.println(name + "睡觉");}
}
class Dog extends Animal {public void wang() {System.out.println(name + "汪汪叫");}
}
class Cat extends Animal {public void miao() {System.out.println(name + "喵喵叫");}
}

在继承时我们需要注意:

1.子类继承父类之后,会继承父类中的成员方法和成员变量(静态成员除外)。
2.子类继承父类之后,必须有子类独有的成员,需体现出与父类的不同,否则没必要继承。

三、父类成员访问

1.成员变量

我们可以在子类中直接访问从父类中继承下来的成员变量

class Fu {public int a;public int b;
}
class Zi extends Fu {public int c;public void test() {a = 10;b = 20;c = 30;System.out.println(a + " " + b + " " + c + " ");}
}
public class Test2 {public static void main(String[] args) {Zi zi = new Zi();zi.test();}
}

但是当父类和子类的成员变量名相同时,会访问哪个呢:

class Fu {public int a = 1;
}
class Zi extends Fu {public int a = 0;public void test() {System.out.println(a);}
}
public class Test2 {public static void main(String[] args) {Zi zi = new Zi();zi.test(); //0}
}

由运行结果可知:成员变量的访问遵循就近原则,如果子类中有,则优先使用子类的成员变量;如果子类中没有,则使用父类的成员变量;若父类和子类均没有,则编译报错。

2.成员方法

我们可以在子类中直接访问从父类中继承下来的成员方法

class Fu {public void test1() {System.out.println("嘻嘻");}
}
class Zi extends Fu {public void test2() {System.out.println("哈哈");}public void test() {test1();test2();}
}
public class Test2 {public static void main(String[] args) {Zi zi = new Zi();zi.test();}
}

但是当父类和子类的成员方法名相同时,会访问哪个呢:

class Fu {public void test1() {System.out.println("嘻嘻");}public void test2(int x) {System.out.println("xixi");}
}
class Zi extends Fu {public void test1() {System.out.println("哈哈");}public void test2() {System.out.println("haha");}public void test() {test1(); //哈哈test2(); //haha(调用子类)test2(666); //xixi(调用父类)}
}
public class Test2 {public static void main(String[] args) {Zi zi = new Zi();zi.test();}
}

由运行结果可知:成员方法的访问遵循就近原则,如果子类中有,则优先使用子类的成员方法;当父类和子类的 同名方法的 参数列表不同时,根据调用方法时传递的参数,选择合适的方法;如果子类中没有,则使用父类的成员方法;若父类和子类均没有,则编译报错。

但是当我们想在子类中访问父类的 同名的成员时,应该怎么办呢?此时,就可以使用super关键字。

四、super关键字

Java中提供了super关键字,帮助我们在子类中访问父类的成员。

class Fu {public int a = 1;public int b = 2;public int c = 3;
}
class Zi extends Fu {public int a = 11;public int d = 4;public void test() {System.out.println(a); //11System.out.println(b); //2System.out.println(c); //3System.out.println(d); //4System.out.println(super.a); //1}
}
public class Test2 {public static void main(String[] args) {Zi zi = new Zi();zi.test();}
}

在这里插入图片描述
对于super关键字:

1.如果super在当前类中被使用,则当前类一定为子类。
2.super只能访问从父类中继承过来的成员。
3.使用this访问,既可以访问父类成员也可以访问子类成员,但当访问父类和子类中同名的成员时,子类成员优先被访问。

因此,子类test方法中以下写法均正确:

        System.out.println(this.a); //11System.out.println(this.b); //2System.out.println(this.c); //3System.out.println(this.d); //4System.out.println(super.a); //1System.out.println(super.b); //2System.out.println(super.c); //3

注意:super关键字只能在非静态方法中使用!!!

五、子类构造方法

class Animal {public String name;public int age;public String sex;//一个参数的构造方法public Animal(String name) {this.name = name;}public void eat() {System.out.println(name + "吃饭");}public void sleep() {System.out.println(name + "睡觉");}
}
class Dog extends Animal {public void wang() {System.out.println(name + "汪汪叫");}
}

我们为动物类提供带有一个参数的构造方法,此时狗类继承动物类时,就会报错。这是因为:当子类继承父类之后,需要先帮助父类进行构造,再构造子类自己。 那又如何帮助父类进行构造呢:在子类中调用父类的构造方法。

构造方法的作用就是对 对象中的成员变量进行初始化,因此需要先调用父类的构造方法,对从父类继承下来的成员完成构造,再调用子类自己的构造方法,对子类中独有的成员进行构造。

于是,我们对代码进行修改:

class Animal {public String name;public int age;public String sex;public Animal(String name) {this.name = name;}public void eat() {System.out.println(name + "吃饭");}public void sleep() {System.out.println(name + "睡觉");}
}
class Dog extends Animal {public Dog(String name) {super(name);}public void wang() {System.out.println(name + "汪汪叫");}
}

在这里插入图片描述
总结一下:

1.当父类显式定义无参或者使用默认提供的构造方法时,子类构造方法的第一行均默认有隐藏的super()调用,即调用父类构造方法。
2.如果父类的构造方法带有参数,则需要显式定义子类的构造方法,并在子类构造方法中调用合适的父类构造方法。
3.在子类构造方法中,super()只能出现在子类构造方法的第一行,因此子类构造方法中只能出现一次super()。

六、super和this辨析


【相同点】
1.均为Java中的关键字。
2.均可以对成员进行访问,且super()和this()都需要在构造方法的首行使用,因此不能同时存在于同一个构造方法。
3.只能在类的非静态方法中使用,用于访问非静态的成员。


【不同点】
1.this代表当前对象的引用,当前对象即调用成员的对象;super代表在子类对象中 对从父类继承下来的成员 的引用。
2.在非静态成员方法中,this既可以访问子类的成员,也可以访问父类的成员;super只能访问父类的成员。
3.在构造方法中,this()用于调用当前类中的构造方法;super()用于调用父类的构造方法。
4.当子类继承父类后,子类的构造方法中一定会存在super()语句,哪怕没有显式定义,编译器也会自动添加;this()不写则没有。


七、再谈初始化

在上一章节中,我们已经学习了有关代码块的知识。在继承关系中,各个代码块的执行顺序又是怎样的呢?

class Animal {public String name;public int age;public String sex;public Animal(String name) {this.name = name;System.out.println("动物构造");}static {System.out.println("动物静态代码块");}{System.out.println("动物实例代码块");}
}
class Dog extends Animal {public Dog(String name) {super(name);System.out.println("小狗构造");}static {System.out.println("小狗静态代码块");}{System.out.println("小狗实例代码块");}
}
public class Test {public static void main(String[] args) {Dog dog1 = new Dog("小狗1");System.out.println("======================");Dog dog2 = new Dog("小狗2");}
}

运行结果为:
在这里插入图片描述
由运行结果我们可以得出:

1.静态代码块优先执行,且父类优先于子类执行。
2.父类的实例代码块和构造方法其次执行。
3.子类的实例代码块和构造方法最后执行。
4.静态代码块只执行一次,第二次实例化对象时,父类和子类的静态代码块均不再执行。

八、protected关键字

在这里插入图片描述
依旧是这张图片,我们来学习一下protected关键字。
在这里插入图片描述


在这里插入图片描述


学习了继承之后,我们对private关键字再补充一点:在父类中被private修饰的成员虽然在子类中不能直接访问,但是也继承到了子类中。

九、继承方式

在Java中支持单继承、多层继承、不同类继承同一个类,但不支持多继承!!!
在这里插入图片描述

十、final关键字

final关键字可以用来修饰变量、方法和类。

final修饰变量时,表示变量不能被修改,即常量:

    public static void main(String[] args) {final int a = 10;a = 20; //×}

final修饰类时,代表类不能被继承:

final class A {
}
//错误×
class B extends A {
}

被final修饰的类,也叫密封类。

final还可以修饰方法,这一点我们以后再介绍。


我们来看一段代码:

        final int[] array = {1,2,3,4,5};array = new int[10]; //1array[0] = 10; //2

这段代码会在1处报错:
在这里插入图片描述

十一、继承与组合

如果将继承比作is-a的关系,那么组合就是has-a的关系。

组合和继承类似,也是一种表达类和类之间关系的方式,也可以达到代码复用的效果。组合的思想体现在代码上 就是将一个类的实例作为另一个类的成员变量,并无特殊的语法格式:

class Old {}
class Home {public Old[] olds;public Home() {this.olds = new Old[2];}
}

Ending。

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

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

相关文章

JS进阶-day1 作用域解构箭头函数

作用域全局作用域——>尽量少使用,避免变量污染局部作用域——>函数作用域、块级作用域作用域链——>底层变量查找机制(先在当前函数作用域查找,如果找不到,就沿着作用域链向上级作用域查找,直到全局作用域&a…

Arduino 无线通信实战:使用 RadioHead实现 315MHz 433M模块数据传输

本文将介绍如何使用 Arduino 和 RadioHead 库实现 315MHz(或 433MHz)ASK 无线通信。通过两个 Arduino 控制板,一个作为发射端,一个作为接收端,实现“按键控制 → 无线发送 → LED 控制”的基础通信功能,非常…

012_PDF处理与文档分析

PDF处理与文档分析 目录 PDF支持概述支持的功能文档限制上传方式分析能力应用场景最佳实践 PDF支持概述 核心能力 Claude现在可以直接处理PDF文档,提供全面的文档分析能力。这项功能支持: 文本内容分析:提取和理解PDF中的文本图像识别&…

系规备考论文:论IT服务知识管理

论IT服务知识管理 摘要 2022年7月,我公司中标某市化工厂网络视频监控管理系统综合平台运维服务项目,并任命我为系统规划与管理师。该项目组织结构为项目型,合同金额为115.5万元(含税),工期为1年。本运维服务项目的主要工作包括系统软件和网络设备的日常监控与维护,定期…

2025.7.12总结

最近又两三天没写总结了,如今必须要写一稿,毕竟事关赚钱认知的一次颠覆。在我原有的认知里,赚钱,就是通过出卖自己的劳动时间,精力,给他人提供价值输出。但是,赚钱,只能通过出卖体力…

把 DNA 当 PCIe:一条 365 nt 链实现 64 Gbps 片上光互连——基于链式 Förster 共振的分子级波分复用链路

作者 | Blossom.118 2025-07-13 关键词:DNA 光子学、FRET 波分复用、分子 PCIe、零能耗光链路、CMOS 兼容、开源版图 ---- 1. 为什么用 DNA 做光互连? • 带宽密度:硅光 1 m 波导最高 0.4 Tbps/mm;一条 2 nm 直径的 DNA 双链&am…

[论文阅读]Text Compression for Efficient Language Generation

Text Compression for Efficient Language Generation [2503.11426] Text Compression for Efficient Language Generation NAACL 2025 提出了“Generative Pretrained Thoughtformer”(GPTHF),这是一个分层 transformer 语言模型&#xf…

SwiftUI 7 新 WebView:金蛇出洞,网页江湖换新天

概述 崇祯年间,华山派武学虽盛,却在应对江湖新局时渐显颓势;如今 SwiftUI 江湖亦是如此 ——WWDC 25 之前,若要在 SwiftUI 中显示网页,开发者恰似袁承志初闯江湖,纵有一身本领,却苦无称手兵刃。…

LeetCode|Day9|976. 三角形的最大周长|Python刷题笔记

LeetCode|Day9|976. 三角形的最大周长|Python刷题笔记 🗓️ 本文属于【LeetCode 简单题百日计划】系列 👉 点击查看系列总目录 >> 📌 题目简介 题号:976. 三角形的最大周长 难度&#x…

华擎B150M Pro4S魔改bios上8代U

100、200系主板魔改bios在DIY领域当属于历史性事件,2018年左右兴起。虽然现在已经是2025年,魔改bios已经没有多大意义,但是跟着前辈的教程魔改一次,可以重温下当年DIY玩家的激情。 魔改教程在SMXDIY网站,写的非常详细&…

音视频学习(三十七):pts和dts

概念 PTS(Presentation Time Stamp)显示时间戳 表示:该帧应该在什么时间被显示/播放。主要用于:同步音频与视频,控制播放节奏。举例:视频帧 A 的 PTS 是 300ms,表示应在视频播放第 300 毫秒时显…

关于数据库的慢查询

1.数据库的慢查询慢查询是指执行时间超过预设阈值的数据库查询操作。它是数据库性能优化的一个重要指标和切入点。慢查询的主要特点执行时间长:超过了数据库系统设定的慢查询阈值(如MySQL默认是10秒)资源消耗大:可能占用大量CPU、…

【Rust日报】 Python 核心开发者对 Rust 的期望

半月刊:The Embedded Rustacean Issue #49亮点:📢 乐鑫 DevCon 2025 演讲嘉宾征集🦺 CISA 和 NSA 参与内存安全对话🔐 微软宣布 RIFT (Rust 恶意软件分析工具)💰️ Nordic 收购 Memf…

vue是什么

Vue简介Vue(Vue.js)是一个用于构建用户界面的渐进式JavaScript框架。它专注于视图层,易于集成到现有项目中,也可用于开发复杂的单页面应用(SPA)。Vue的核心特点是轻量、灵活和高效,通过数据绑定…

10分钟掌握 Nginx 配置文件结构

在实际部署前端或后端项目时,Nginx 配置文件(nginx.conf) 是我们无法绕开的第一道门槛。 本文将带你用10分钟掌握 nginx.conf 的核心结构与常见配置方法,并提供一篇完整的实战文档链接,适合初学者快速掌握。 &#x1…

典型的前后端交互数据示例

提供几种典型的前后端交互数据示例: 前端如何组织数据,以及后端如何接收数据。 文章目录1. POST请求后端实体类接收前端js后端接收结果查看2. GET请求后端实体类接收前端js后端接收结果查看3. GET请求后端基本类型接收前端js后端接收结果查看1. POST请求…

计算机毕业设计springboot影视周边推荐系统 基于SpringBoot的电影衍生品智能推荐平台 JavaWeb实现的影视文化周边个性化服务系统

计算机毕业设计springboot影视周边推荐系统6c31q9 (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。疫情之后,线上娱乐需求激增,人们对电影及其衍生商品的关…

(4)机器学习小白入门YOLOv :图片标注实操手册

(1)机器学习小白入门YOLOv :从概念到实践 (2)机器学习小白入门 YOLOv:从模块优化到工程部署 (3)机器学习小白入门 YOLOv: 解锁图片分类新技能 (4)机器学习小白入门YOLOv :图片标注实操手册 (5)机器学习小白入门 YOLOv:…

【JMeter】调试方法

文章目录取样器:发送请求、接收响应>>察看结果树断言:验证响应>>察看结果树提取器:创建变量>>调试取样器自定义断言:代码>>日志了解JMeter的内部细节,排查错误的原因。取样器:发送…

Vue框架之钩子函数详解

Vue框架之生命周期主要钩子函数详解一、Vue生命周期的整体流程二、创建阶段:初始化组件实例2.1 beforeCreate:实例创建前2.2 created:实例创建后三、挂载阶段:组件与DOM结合3.1 beforeMount:挂载前3.2 mounted&#xf…