JavaSE-继承

继承(inheritance)

继承的意义

我们首先来看下面两个类:

public class Dog {public String name;public int age;public void eat(){System.out.println(this.name+"正在吃饭");}public void bark(){System.out.println(this.name+"正在汪汪叫");}
}
public class Cat {public String name;public int age;public void eat(){System.out.println(this.name+"正在吃饭");}public void miao(){System.out.println(this.name+"正在喵喵叫");}
}

这两个名为Dog和Cat的类拥有相同的成员变量name、age以及相同的成员方法eat

在主方法中可以正常调用他们的变量和方法。

public class test {public static void main(String[] args) {Dog dog = new Dog();dog.name="大黄";dog.eat();dog.bark();System.out.println("============");Cat cat = new Cat();cat.name="大橘";cat.eat();cat.miao();}
}

 我们可以发现在Dog和Cat中就具有相同的成员,如果每次新建一个动物类时都要加入这些相同成员,未免有些麻烦,于是继承出现了。

如何继承

新建一个Animals类,将动物所具有的共同成员放入其中并删去原来类中的共同成员。

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

在原来的类名后加上extends Animals。

格式如下:

修饰符 class 子类名 extends 父类名{

public class Dog extends Animals{public void bark(){System.out.println(this.name+"正在汪汪叫");}
}
public class Cat extends Animals{public void miao(){System.out.println(this.name+"正在喵喵叫");}
}

这样原来的主函数依然可以正常运行。Animals就称为父类/基类/超类,Dog和Cat就叫做子类或者派生类。通过继承,我们实现了代码的复用。

继承中的访问与调用

子类访问父类成员变量

下面三段代码分别是子类,父类和主方法。

package demo2;public class Derived extends Base{public int c=3;public void func(){System.out.println(this.a);System.out.println(this.b);System.out.println(this.c);}
}
package demo2;public class Base {public int a=1;public int b=2;
}
package demo2;public class test {public static void main(String[] args) {Derived derived =new Derived();derived.func();}
}

运行结果:

 子类访问了继承自父类的a和b,并访问了自身的成员变量c。

在子类中加入a=100:

package demo2;public class Derived extends Base{public int c=3;public int a=100;public void func(){System.out.println(this.a);System.out.println(this.b);System.out.println(this.c);}
}

运行结果:

可见当父类和子类中同时出现变量a时,this关键字访问的是子类自身的a。

如何在子类中访问父类中的同名变量a?

使用super关键字。

package demo2;public class Derived extends Base{public int c=3;public int a=100;public void func(){System.out.println(super.a);System.out.println(this.b);System.out.println(this.c);}
}

运行结果:

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

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

2.如果访问的成员变量子类中无,则访问父类继承下来的,如果父类中也无,则编译报错。

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

子类访问父类成员方法

当子类中成员方法与父类中成员方法不同名时,可以直接在子类中调用父类成员方法:

public class Base {public int a=1;public int b=2;public void testBase(){System.out.println("testBase---");}
}
public class Derived extends Base{public int c=3;public int a=100;public void testDerived(){System.out.println("testDerived---");}public void test(){testBase();testDerived();}
}

public class test {public static void main(String[] args) {Derived derived =new Derived();derived.test();}
}

运行结果:

 当子类中方法与父类中方法重名时,优先就近原则调用子类自己的方法,同时可以构成方法的重载和方法的重写:

方法的重载:

public class Base {public int a=1;public int b=2;public void testA(){System.out.println("testA()---");}
}public class Derived extends Base{public int c=3;public int a=100;public void testA(char a){System.out.println("testA(char a)---");}public void test(){testA();testA('a');}
}public class test {public static void main(String[] args) {Derived derived =new Derived();derived.test();}
}

 并且可以使用super关键字调用父类方法:

public class Base {public int a=1;public int b=2;public void testA(){System.out.println("testA(Base)---");}
}public class Derived extends Base{public int c=3;public int a=100;public void testA(){System.out.println("testA(Derived)---");}public void test(){testA();super.testA();}
}public class test {public static void main(String[] args) {Derived derived =new Derived();derived.test();}
}

运行结果:

但是super只能指代父类,不能指代父类的父类玩套娃。

当子类继承父类之后,在不使用构造方法的情况下,java会自动为子类和父类提供构造方法,但当我们为类添加构造方法时,子类需要显式的调用父类的构造方法,帮助父类完成初始化。

public class Animals {public String name;public int age;public void eat(){System.out.println(this.name+"正在吃饭");}public Animals(String name,int age){this.name=name;this.age=age;}
}public class Dog extends Animals {public void bark(){System.out.println(this.name+"正在汪汪叫");}public Dog(String name,int age){super(name,age);}
}public class test {public static void main(String[] args) {Dog dog = new Dog("大黄",3);System.out.println("name:"+dog.name+" age:"+dog.age);}
}

简而言之,当为父类添加构造方法时,需要同时在子类中添加构造方法并在第一行使用super关键字帮助父类初始化。

super和this关键字

1.super()和this()构造方法只能在第一行使用,并且不能同时出现。 

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

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

4.构造方法中一定会有super()的调用,即使用户没有写编译器也会添加,但this()用户不写则没有。

继承中的代码块运行顺序

猜测下列标号代码块的运行顺序:

public class Animals {public String name;public int age;static{System.out.println("static::Animal{}");}//1{System.out.println("实例化代码块 Animal");}//2public Animals(String name,int age){this.name=name;this.age=age;System.out.println("Animal()");}//3
}public class Cat extends Animals {static{System.out.println("static::Cat{}");}//4{System.out.println("实例化代码块 Cat{}");}//5public void miao(){System.out.println(this.name+"正在喵喵叫");}public Cat(String name,int age){super(name,age);System.out.println("Cat()");}//6
}public class test {public static void main(String[] args) {Cat cat=new Cat("大橘",4);}
}

运行结果:

运行顺序是:142356

从中可以得出代码块的运行逻辑:先执行父类,子类的静态代码块,再执行父类的实例化和初始化,再执行子类的实例化和初始化。

 继承的权限

private:仅允许本类中调用

default:允许同包中的不同类使用

protected:允许不同包中的子类使用

public:允许不同包的非子类中使用

在继承的权限使用中,我们要尽可能的做到封装:即最大的私密性,隐藏内部细节,只显露出必要的内容给使用者,能够使用private,就尽量不要使用public。有一个暴力的方法,就是将所有的变量设置为private权限,将所有的方法设置为public权限。

final关键字

继承关系不宜有太多层,一般三层为上限。final在java中对变量修饰可以将其变为不可改变的常量,对子类修饰则可以防止这个类被继承,当它被继承时编译器会报错,这个类就被称为密封类。

继承与组合

继承中子类与父类的关系可以表示为子类 is a 父类,而组合可以表示为前者 has a后者,或者后者 is a part of 前者,如汽车和轮胎的关系。

class Student{}class Teacher{}public class school {public Student[] student=new Student[10];public Teacher[] teacher=new Teacher[10];
}

学生和老师是学校的一部分,这就是组合关系。

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

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

相关文章

第二届虚拟现实、图像和信号处理国际学术会议(VRISP 2025)

重要信息 官网:www.icvisp.net 时间:2025年8月1-3日 地点:中国-长沙 简介 近年来,虚拟现实技术取得了显著进步,与5G、云计算和物联网等新一代信息技术的融合加速,推动了其在硬件、软件和内容应用等方面…

SpringBoot+Mybatis+MySQL+Vue+ElementUI前后端分离版:整体布局、架构调整(二)

目录 一、前言 二、后端调整 1.实体类调整 2.菜单相关接口 3.用户相关接口 4.新增工具类 5.新增菜单树返回类 6.配置类、拦截器 三、前端调整 1.请求调整 2.页面布局、样式调整 1.user.vue 2.index.vue 3.请求拦截 四、开发过程中的问题 五、附&#xff1a…

vue3官方文档学习心得

这几天抽空把vue3的文档整个看了一遍。简介 | Vue.js 23年写过一个vue2的项目,24年写了一个vue3的项目,页面功能比较简单,用几个简单的API,watch、watchEffect、ref、reactive就能实现的业务功能。 写了几年的react的&#xff0…

Pycharm恢复默认设置,配置导致复制粘贴等不能使用

在file 种找到manage IDE settings在manage IDE settings中找到restore default settings

【王树森推荐系统】召回12:曝光过滤 Bloom Filter

概述 曝光过滤通常是在召回阶段做,具体的方法就是用 Bloom Filter 曝光过滤问题 如果用户看过某个物品,则不再把该物品曝光给用户。原因是同一个物品重复曝光给用户会损害用户体验,但也不是所有推荐系统都有曝光过滤,像 youtube 这…

基于STM32单片机的心率血氧监测系统设计(STM32代码编写+手机APP设计+PCB设计+Proteus仿真)

系列文章目录 文章目录 系列文章目录前言1 资料获取与演示视频1.1 资料介绍1.2 资料获取1.3 演示视频 2 系统框架3 硬件3.1 主控制器3.2 显示屏3.3 WIFI模块3.4心率血氧传感器 4 设计PCB4.1 安装下载立创EDA专业版4.2 画原理图4.4 使用嘉立创下单助手进行下单,打板。…

main(int argc,char **agrv)的含义

今天和大家讨论一个常见的但是不容易深入了解的知识点。那就是 main 函数声明中使用到的 argc 和 argv 的含义。通常我们写主函数的时候一般都是直接使用int main() 或者 void main() 来声明 main 函数。但是你知道吗?在c89/c99的语言标准中,main函数的声…

如何简单实现发版不影响客户使用?nginx负载

nginx负载发版不影响客户使用 1.需要二台服务器 2.二台服务器均是正式环境配置 3.服务器Nginx配置修改 发版顺序:先在服务器2发版,发布成功后,再改服务器Nginx配置,重新加载nginx;然后在服务器再发版,发布成…

qt笔记(1)——Qtablewidget使用

1.基础使用方法 (略) 2.坑和注意点 2.1 设置一个单元格的编辑属性 在代码中,想要修改一个单元格的编辑属性,需要对这个item的flags进行设置;注意对一个tablewidget的一个item成员进行设置后,进行一次编…

字符串的模糊匹配方法介绍

字符串的模糊匹配方法介绍 目录字符串的模糊匹配方法介绍一、编辑距离(Levenshtein Distance)复杂度分析二、Jaro-Winkler 距离复杂度分析三、最长公共子序列(LCS)复杂度分析四、模糊搜索(Fuzzy Search)复杂…

ActiveMQ在Spring Boot中的详细使用指南

📋 目录 🚀 ActiveMQ简介 什么是ActiveMQ? 核心概念 🏗️ 基础架构组件 📝 重要概念解释 ActiveMQ vs 其他消息中间件 🔧 环境搭建 1. ActiveMQ服务端安装 Docker方式(推荐初学者) 手动安装方式 2. 验证安装 访问Web管理界面 连接参数 测试连接 �…

二元一次方程

前言 最近刚学二元一次方程,想写一篇专栏熟悉一下本文写给初一的同学看,学过的就划了吧二元一次方程 两个未知数最高项次数为 111 次为整式方程二元一次方程的解不唯一,但是二元一次方程可以用一个未知数来表达另一个未知数eg:eg:eg: xy1x y…

AI编程的未来是智能体原生开发?

目录 前言 一、从“串行”到“并行”:什么是智能体原生开发? 1.1 传统模式(串行思维) 1.2 智能体原生模式(并行思维) 二、程序员的新角色:从代码手艺人到系统思想家 三、软件开发的终局&a…

【牛客刷题】小红的与运算

文章目录 一、题目介绍1.1 题目描述1.2 输入描述1.3 输出描述1.4 示例二、 解题思路2.1 核心算法设计2.2 性能优化关键2.3 算法流程图三、解法实现3.1 解法一:基础实现3.1.1 初级版本分析3.2 解法二:优化版本(推荐)3.2.1 优化版本分析四、总结与拓展4.1 关键优化技术4.2 算…

spring中 方法上@Transation实现原理

Spring中Transactional注解方法实现原理Spring的Transactional注解在方法级别实现事务管理的原理主要基于动态代理和拦截器机制,以下是其核心实现流程:1. 代理创建阶段当Spring容器启动时,会为带有Transactional注解的类创建代理对象&#xf…

qt-C++语法笔记之Stretch与Spacer的关系分析

qt-C语法笔记之Stretch与Spacer的关系分析 code review! 文章目录qt-C语法笔记之Stretch与Spacer的关系分析1. Stretch(拉伸因子)2. Horizontal Spacer 和 Vertical Spacer3. Stretch 和 Spacer 的关系4. 实际应用中的选择5. 注意事项6. 代码与 Qt Desig…

Qwen3技术综述

1. 引入 2025年5月,qwen推出了旗舰模型(flagship model)Qwen3-235B-A22B。并以Apache 2.0版权发布(可自由商业使用,修改代码和商用要包含原始版权)。本文对其技术报告中提到的数据处理技术与模型结构进行综…

[特殊字符] Excel 读取收件人 + Outlook 批量发送带附件邮件 —— Python 自动化实战

许多公司定期需要将不同部门或客户的报告发送给指定人员。手动操作容易出错、耗时且繁琐。今天这篇文章教你如何利用 Python 实现: 🧩 从 Excel 中读取“收件人 抄送人 附件文件路径”; 📤 使用 win32com.client 调用 Outlook …

多模态大语言模型arxiv论文略读(152)

VidComposition: Can MLLMs Analyze Compositions in Compiled Videos? ➡️ 论文标题:VidComposition: Can MLLMs Analyze Compositions in Compiled Videos? ➡️ 论文作者:Yunlong Tang, Junjia Guo, Hang Hua, Susan Liang, Mingqian Feng, Xinya…

基于AR和SLAM技术的商场智能导视系统技术原理详解

本文面对室内定位算法工程师、智慧商场系统开发者、对VR/AR应用开发感兴趣的技术人员,解决如何通过SLAMAR技术破解大型商场室内导航的空间认知壁垒,实现沉浸式导览,本文提供完整技术方案与代码实现。 如需获取商场智能导视系统解决方案请前往…