【JAVA】面向对象三大特性之继承

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、继承的概念和使用细则
    • 1.1 继承的基本使用和含义
    • 1.2 关于子类访问父类成员的问题
    • 1.3 super关键的引出
    • 1.4 super调用父类当中指定的构造方法
    • 1.5 关于super和this
    • 1.6 继承关系上的代码块执行顺序
    • 1.7 访问修饰限定符-protected关键字
    • 1.8 java中的继承方式
    • 1.9 final关键字
  • 二、继承和组合
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:

继承作为面向对象编程的核心支柱,通过对类之间共性的高效抽取实现代码复用,为构建层次化、可扩展的软件系统奠定坚实基础。


提示:以下是本篇文章正文内容,下面案例可供参考

一、继承的概念和使用细则

1.1 继承的基本使用和含义

继承(inheritance)机制:是⾯向对象程序设计使代码可以复⽤的最重要的⼿段,它允许程序员在保持原有类特性的基础上进⾏扩展,增加新功能,这样产⽣新的类,称派⽣类。

继承的目的就是对不同类之间进行共性的抽取,从而来实现代码的复用!!!!!!

在这里插入图片描述
被继承的类称为父类、基类和超类,继承别人的类称为子类和派生类,和生活中的情形很接近所以很好理解。
在代码中,继承最大的特性就是子类可以继承父类当中的成员变量和成员方法!!

接下来对上述图示中的类之间的关系,利用继承用代码进行实现。

package com.dzj;public class Animal {public String name;public int age;public float weight;public void eat(){System.out.println(name+"---吃东西---");}public void sleep(){System.out.println(name+"开始睡觉~~~~~");}
}
package com.dzj;public class Cat extends Animal{public void mew(){System.out.println(name+"喵喵喵");}
}
package com.dzj;public class Dog extends Animal{public void bark(){System.out.println(this.name+"狗叫");}
}
package com.dzj;public class TestExtend {public static void main(String[] args) {Cat cat=new Cat();cat.name="hzp";cat.eat();cat.sleep();cat.mew();Dog dog=new Dog();dog.name="xxx";dog.eat();dog.sleep();dog.bark();}
}

在这里插入图片描述

1.2 关于子类访问父类成员的问题

关于这个问题,只要遵循一个就近原则即可:如果子类有优先访问子类的,子类没有的再去父类找!!!!

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

package com.demo1;public class Base {int a=10;int b=20;
}
package com.demo1;public class Derived extends Base{int c=30;public void method(){System.out.println(a);System.out.println(b);System.out.println(c);}
}
package com.demo1;public class Test {public static void main(String[] args) {Derived derived=new Derived();derived.method();}
}

在这里插入图片描述
结果表明,如果子类和父类不存在同名的成员变量,子类可以直接访问父类的成员变量。

如果子类和父类存在同名成员变量:

package com.demo1;public class Base {int a=10;int b=20;
}
package com.demo1;public class Derived extends Base{int a=100;int b=200;int c=30;public void method(){System.out.println(a);System.out.println(b);System.out.println(c);}
}
package com.demo1;public class Test {public static void main(String[] args) {Derived derived=new Derived();derived.method();}
}

在这里插入图片描述
结果表明,如果父子类出现同名的成员变量,优先使用子类的成员变量,即遵循就近原则。

对于子类访问父类的成员方法其实原理比较类似,接下来直接上代码解释:

package com.demo1;public class Base {int a=10;int b=20;public void methodA(){System.out.println("Base的methodA--------");}public void methodB(int x){System.out.println("Base的methodA--------");System.out.println(x);}
}
package com.demo1;public class Derived extends Base{int a = 100;int b = 200;int c = 30;public void method(){System.out.println(a);System.out.println(b);System.out.println(c);}public void methodA(){System.out.println("Derived的methodA--------");}public void methodB(){System.out.println("Derived的mmethodB--------");}public void methodC(){System.out.println("Derived的methodC--------");}
}
package com.demo1;public class Test {public static void main(String[] args) {Derived derived=new Derived();derived.methodA();derived.methodB();derived.methodB(100);derived.methodC();}
}

在这里插入图片描述
从结果可以看出整个调用过程还是遵循就近原则的,唯一需要注意的是成员方法本身是支持重载的,如果存在方法的重载根据所给参数的不同来确定最后调用的是哪一个成员方法。

1.3 super关键的引出

问题:如果⼦类中存在与⽗类中相同的成员时,那如何在⼦类中访问⽗类相同名称的成员呢?,也就是说如果存在同名的情况,我一定要访问父类的成员变量和成员方法怎么做???

答案就是利用super关键字,接下来将用代码进行演示super关键的作用,最后在做一个小的总结。

package com.demo1;public class Base {int a=10;int b=20;public void methodA(){System.out.println("Base的methodA--------");}public void methodB(int x){System.out.println("Base的methodA--------");System.out.println(x);}
}
package com.demo1;public class Derived extends Base{int a = 100;int b = 200;int c = 30;public void method(){System.out.println(a);System.out.println(b);System.out.println(c);System.out.println(super.a);System.out.println(super.b);super.methodA();}public void methodA(){System.out.println("Derived的methodA--------");}public void methodB(){System.out.println("Derived的mmethodB--------");}public void methodC(){System.out.println("Derived的methodC--------");}
}
package com.demo1;public class Test {public static void main(String[] args) {Derived derived=new Derived();/*derived.methodA();derived.methodB();derived.methodB(100);derived.methodC();*/derived.method();}
}

在这里插入图片描述
从结果可以看出,在子类成员方法中可以使用super关键字访问父类的成员变量和成员方法

注意事项
**1. 只能在非静态⽅法中使用(和this关键字一样)

  1. 在⼦类⽅法中,访问⽗类的成员变量和⽅法。**

1.4 super调用父类当中指定的构造方法

package com.demo2;public class Base {public Base(int x){System.out.println("Base构造方法");System.out.println(x+"----"+x);}
}
package com.demo2;public class Derived extends Base{public Derived() {System.out.println("Derived构造方法");}
}
package com.demo2;import com.demo1.Derived;public class Test {public static void main(String[] args) {Derived derived=new Derived();}}

在这里插入图片描述
上述结果表明Base构造方法缺少参数,出现错误的原因就是,在构建子类对象的同时,要先完成父类的构造函数初始化在完成子类构造函数的初始化!

public class Derived extends Base{public Derived() {super(100);System.out.println("Derived构造方法");}
}

稍作修改就可以编译成功!
在这里插入图片描述
【注意事项】
• 通过super(参数)的形式可以调⽤⽗类指定的构造⽅法
• super()的形式只能出现在⼦类的构造⽅法当中且必须在第⼀⾏

再思考一个问题:先看如下代码

package com.demo2;public class Base {public Base(){System.out.println("Base构造方法");/*System.out.println(x+"----"+x);*/}
}
package com.demo2;public class Derived extends Base{public Derived() {/*super(100);*/System.out.println("Derived构造方法");}
}
package com.demo2;import com.demo2.Derived;public class Test {public static void main(String[] args) {Derived derived=new Derived();}
}

在这里插入图片描述
代码可以正常运行!!!为什么这里没用super也能跑,因为再子类构造方法的第一行系统默认会加上一个super()调用父类无参构造方法。仅限⽗类的构造⽅法是不带参数的构造⽅法且只有这⼀个的情况下。
另外补充一点,super()和this()是不能一起使用的!!!,因为他们都要求放在构造函数第一行上

1.5 关于super和this

【相同点】
1. 都是Java中的关键字
2. 只能在类的⾮静态⽅法中使⽤,⽤来访问⾮静态成员⽅法和字段
3. 在构造⽅法中调⽤时,必须是构造⽅法中的第⼀条语句,并且不能同时存在

【不同点】
1. this是当前对象的引⽤,当前对象即调⽤实例⽅法的对象,super相当于是⼦类对象中从⽗类继承下
来部分成员的引⽤

在这里插入图片描述
从图中可以看出,super和this指向的是不同的空间。
2. 在⾮静态成员⽅法中,this⽤来访问本类的⽅法和属性,super⽤来访问⽗类继承下来的⽅法和属性
4. 在构造⽅法中:this(…)⽤于调⽤本类构造⽅法,super(…)⽤于调⽤⽗类构造⽅法,两种调⽤不能同时在构造⽅法中出现
5. 构造⽅法中⼀定会存在super(…)的调⽤,⽤⼾没有写编译器也会增加,但是this(…)⽤⼾不写则没有

1.6 继承关系上的代码块执行顺序

package com.demo3;
public class Person {String name;int age;public Person(String name,int age){this.name=name;this.age=age;System.out.println("Person:构造方法执行");}{System.out.println("Person:实例代码块执行");}static{System.out.println("Person:静态代码块执行");}
}
package com.demo3;public class Student extends Person{
public Student(String name,int age){super(name,age);System.out.println("Student:构造方法执行");
}{System.out.println("Student:实例代码块执行");}static{System.out.println("Student:静态代码块执行");}
}
package com.demo3;public class Test {public static void main(String[] args) {Student student1=new Student("dzj",18);System.out.println("--------------------");Student student2=new Student("dzj",18);}
}

在这里插入图片描述

通过分析执⾏结果,得出以下结论:
1. ⽗类静态代码块优先于⼦类静态代码块执⾏,且是最早执⾏。
2. ⽗类实例代码块和⽗类构造⽅法紧接着执⾏。
3. ⼦类的实例代码块和⼦类构造⽅法紧接着再执⾏。

4. 第⼆次实例化⼦类对象时,⽗类和⼦类的静态代码块都将不会再执⾏

1.7 访问修饰限定符-protected关键字

在这里插入图片描述
如果被protected 关键字修饰该类当中成员变量,成员⽅法等表⽰要么只能在同⼀个包中的类中进⾏访问,要么在不同包中只能通过在继承关系上的⼦类对象来访问

package com.demo2;public class Base {/*  public Base(){System.out.println("Base构造方法");*//*System.out.println(x+"----"+x);*//*}*/protected int x=100;
}
package com.demo3;import com.demo2.Base;public class Derived extends Base {public static void main(String[] args) {Derived derived=new Derived();System.out.println(derived.x);}
}

在这里插入图片描述
打印结果表明:不同包下的子类可以访问父类中被protected修饰的成员变量.

特殊情况:

package com.demo3;import com.demo2.Base;
class C extends Base{public static void main(String[] args) {C c=new C();System.out.println(c.x);}
}public class Derived extends Base {public static void main(String[] args) {Derived derived=new Derived();System.out.println(derived.x);C c=new C();System.out.println(c.x);}
}

在这里插入图片描述
虽然Derived 类继承⾃Base 类,但它不能访问其他 Base 类⼦类(这⾥是C类)实例的protected 成员。可能感觉比较抽象,一个简单的理解就是要访问protected修饰的变量,那么只能在本类中用自己的对象去访问,不能用别人的,所以个人认为这个protected的访问有比较大的局限性。
总结:
如果在情况允许下,能用private就用private,这样能最大程度的保持封装性,因此我们在使⽤的时候应该尽可能的使⽤⽐较严格的访问权限。

1.8 java中的继承方式

在这里插入图片描述
java中不允许多继承的存在,⼀般我们不希望出现超过三层的继承关系

1.9 final关键字

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

final修饰变量即为常量,不可以发生改变

public final class Animal {
}
public class Bird extends Animal{}

final修饰类即为不可继承
final修饰方法即为该方法不可以被重写,这一点再后续的博客中再讲解。

二、继承和组合

继承表⽰对象之间是is-a的关系,⽐如:狗是动物,猫是动物
组合表⽰对象之间是has-a的关系,⽐如:汽⻋

用代码来解释更清楚:

package com.demo4;public class Car {private Tire tire;private Engine engine;public Tire getTire() {return tire;}public void setTire(Tire tire) {this.tire = tire;}public Engine getEngine() {return engine;}public void setEngine(Engine engine) {this.engine = engine;}
}
package com.demo4;public class Engine {int size;
}
package com.demo4;public class Tire {String color;
}
package com.demo4;public class Benz extends Car{public static void main(String[] args) {Benz benz =new Benz();Tire tire=new Tire();Engine engine=new Engine();engine.size=100;tire.color="黑色";benz.setTire(tire);benz.setEngine(engine);System.out.println(benz.getEngine().size);System.out.println(benz.getTire().color);}}

在这里插入图片描述
组合和继承都可以实现代码复⽤,应该使⽤继承还是组合,需要根据应⽤场景来选择,⼀般建议:能⽤组合尽量⽤组合,继承层次太深的代码不利于维护。

总结

从基础使用到访问控制,从super关键字到代码块执行顺序,深入理解继承机制能显著提升代码复用性和可维护性,但需警惕过度继承带来的设计复杂性,合理运用final和组合优化架构。

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

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

相关文章

基于深度学习的自动调制识别网络(持续更新)

基于卷积神经网络架构 CNN 参考文献 T.J. O’Shea, J. Corgan, T.C. Clancy, Convolutional radio modulation recognition networks, in: Proc. Int. Conf. Eng. Appl. Neural Netw., Springer, 2016, pp. 213–226. MCNet 参考文献 T. Huynh-The, C.-H. Hua, Q.-V. Pha…

Java进阶---并发编程

一.线程复习1.什么是线程,进程进程是操作系统分配资源的基本单位线程是进程中的一个执行单元(一个独立执行的任务),是cpu执行的最小单元2.Java中如何创建线程1.继承Thread类,重写run(),直接创建子类的对象2.类实现Runnable接口&am…

小车循迹功能的实现(第六天)

👨‍💻个人主页:开发者-削好皮的Pineapple! 👨‍💻 hello 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 削好皮的Pineapple! 原创 👨‍&#x1f4…

C++ auto与 for循环

一、数组 #include <iostream> #include <vector> using namespace std; int main() {int vec[6] {1,2,3};for (auto num : vec) { /* num 是 int */ cout << "Hello, world!" << num <<endl;}return 0; }二、STL容器与迭代器 for 循…

【RK3568+PG2L50H开发板实验例程】FPGA部分 | ROM、RAM、FIFO 的使用

本原创文章由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处&#xff08;www.meyesemi.com) 1.实验简介 实验目的&#xff1a; 掌握紫光平台的 RAM、ROM、FIFO IP 的使用 实验环境&#xff1a; Window11 PDS2022…

力扣-21.合并两个有序链表

题目链接 21.合并两个有序链表 class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode p1 list1;ListNode p2 list2;ListNode p new ListNode(0);ListNode cur p;while (p1 ! null && p2 ! null) {if (p1.val > p2.val) …

MoE混合专家模型:千亿参数的高效推理引擎与架构革命

本文由「大千AI助手」原创发布&#xff0c;专注用真话讲AI&#xff0c;回归技术本质。拒绝神话或妖魔化。搜索「大千AI助手」关注我&#xff0c;一起撕掉过度包装&#xff0c;学习真实的AI技术&#xff01; 从稀疏激活到多模态协同的智能计算范式 &#x1f9e9; 一、核心思想与…

【论文笔记】BlockGaussian:巧妙解决大规模场景重建中的伪影问题

论文地址&#xff1a;https://arxiv.org/pdf/2504.09048 大规模场景的重建方法不仅仅对于高空航拍数据有效&#xff0c;而且对于地面大中场景也有增强效果&#xff0c;故专门来学习一下这一方向的知识。感谢作者大佬们的great work。 Abstract 三维高斯泼溅&#xff08;3DGS…

网络众筹项目数据库(2014-2024.11)

1727网络众筹项目数据库&#xff08;2014-2024.11&#xff09;数据简介作为新兴互联网融资模式&#xff0c;众筹已成为越来越多创业者和中小企业获取资金的渠道&#xff0c;但众筹项目一直面临融资成功率低的困难&#xff0c;成功融资的项目在许多平台上占比不足五成。而目前对…

k8s新增jupyter服务

k8s新增服务 常用命令 kubectl apply -f xxxxxx.yaml # 部署资源&#xff0c;顺序&#xff1a;namespace -> pvc -> deployment -> servicekubectl create namespace jupyter # 创建namespacekubectl get namespaces # 查看nskubectl get pods -n jupyter # 查看p…

结构化数据、非结构化数据区别

一、核心定义结构化数据&#xff1a;指具有固定格式、可直接用二维表&#xff08;如数据库表&#xff09;表示的数据&#xff0c;其字段&#xff08;列&#xff09;定义明确&#xff0c;数据之间的关系清晰。例如&#xff1a;Excel 表格中的数据、关系型数据库&#xff08;MySQ…

Linux修炼:基础指令

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》、《Linux修炼&#xff1a;终端…

【Linux网络】深入理解HTTP/HTTPS协议:原理、实现与加密机制全面解析

协议是通信双方必须遵守的规则&#xff0c;确保数据能够正确传输和解析&#xff0c;它规定了数据格式、传输顺序、错误处理等细节。应用层的协议一般都是我们自己进行定义的&#xff0c;但是有很多程序员前辈已经写出来了很哇塞的协议&#xff0c;我们直接进行学习和使用即可HT…

浅尝 Spring AI【使用超级简单~】

一直想要体验下 Spring AI&#xff0c;最近自己的一个工具有这个需求&#xff0c;所以这里准备使用下。其实使用起来超级简单。 1.IDEA 新建 Spring项目 1&#xff09;这里可以根据自己的喜好选择 项目名、jdk版本等 2&#xff09;这里选择 在ai中选择 openAI 即可。然后我另…

DDL期间TDSQL异常会话查询造成数据库主备切换

问题描述&#xff1a;7*24联机交易系统&#xff0c;傍晚时分&#xff0c;从客户端后台对3千万行的大表执行缩短varchar类型字段长度的ddl语句&#xff0c;执行期间&#xff0c;为了查看ddl进度&#xff0c;从TDSQL-MySQL赤兔前端页面点击异常会话查询&#xff0c;之后数据库卡住…

弧焊机器人气体全方位节能指南

氩弧焊&#xff08;TIG焊接&#xff09;作为其中一种高效且精密的技术&#xff0c;凭借其稳定性和高质量的焊接效果&#xff0c;在航空航天、汽车制造、船舶建造以及石油化工等领域占据了不可或缺的地位。氩弧焊通过使用惰性气体&#xff08;如氩气&#xff09;保护电弧和熔池&…

数据清洗(ETL/ELT)原理与工具选择指南:企业数字化转型的核心引擎​

目录 一、数据清洗&#xff08;ETL/ELT&#xff09;到底在干啥&#xff1f; 1.揪出并处理异常值 2.把缺失的数据补上&#xff08;或处理好&#xff09; 3.数据转换与标准化 4.一致性校验 二、工具怎么选&#xff1f;看菜吃饭&#xff0c;量体裁衣 1.数据量不大、要求不高…

阿里云服务器,CentOS7.9上安装YApi 接口管理平台

目录 1.node安装 1.1下载node,解压 1.2 部署bin文件 1.3 安装mongodb 2.启动yapi 2.1 前置命令 2.2 启动服务 3.利用pm2方便服务管理维护 3.1.安装pm2 3.2 常用 PM2 命令 4.常见问题 4.1. 确认 MongoDB 是否安装 4.2. 安装 MongoDB&#xff08;若未安装&#xff…

阿里云错题集分享

有最近想要考试阿里云的可以私信我 &#xff0c;一起加油错题集1.在使用阿里云的负载均衡SLB实例时&#xff0c;做了如下健康检查的配置:成功响应和超时响应时间均为1秒&#xff0c;健康检查间隔为2秒&#xff0c;不健康阈值为3&#xff0c;健康阈值为3。即对于确认一个云服务器…

Android 12 - 部分相机横屏显示方案

1.相机过渡界面方向旋转 Android 10 - 相机过渡界面默认角度 同A10 有些区别&#xff0c;再次增加记录修改。 这个文件没有修改&#xff0c;只是说明 src/com/android/camera/CameraActivity.javaprivate void freezeScreenCommon(boolean async) {long startTime System.…