类的继承和super,final关键字的使用(JAVA)

简介: 类的继承和super,final关键字的使用(JAVA)

继承

所有的OOP语言都会有三个特征:

    1. 封装(点击可跳转)
    2. 继承
    3. 多态(点击可跳转)

    为什么会有继承呢?可以先看下面的例子:


    image.png

    image.png

    上面这两个类中的代码很相似因为它们只有最后一个方法不同其它的都相同,这样定义不但导致代码冗余而且非常麻烦。而在OOP语言中继承就是专门用来进行共性抽取,实现代码复用。


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

    在JAVA中要实现继承需要借助extends关键字。

    修饰符 class 子类 extends 父类 {

    // ...

    }

    此时我们在看再面的例子老师和学生都属于人这个大类,那么我们就可以单独定义一个People类来将他们相同的属性和方法放在一起,然后由学生类和老师类分别继承人这个大类:

    classPeople{
    publicStringname;
    publicintage;
    publicvoidspeak(){
    System.out.println(this.name+"正在说话");
        }
    }
    classTeacherextendsPeople{
    publicvoidwork(){
    System.out.println(this.name+"正在教书");
        }
    }
    classStudentextendsPeople{
    publicvoidstudy(){
    System.out.println(this.name+"正在学习");
        }
    }
    publicclassTest {
    publicstaticvoidmain(String[] args) {
    Teacherteacher=newTeacher();
    teacher.name="zhangsan";
    teacher.age=24;
    teacher.speak();
    teacher.work();
    System.out.println("==========");
    Studentstudent=newStudent();
    student.name="xiaoming";
    student.age=15;
    student.speak();
    student.study();
        }
    }

    image.gif

    image.png


    注意:子类会将父类中的成员变量或者成员方法继承到子类中。

    那么现在又有一个新问题如果子类中有和父类相同的属性或方法那系统会怎么办?

    classPeople{
    publicStringname;
    publicintage=25;
    publicvoidspeak(){
    System.out.println(this.name+"正在说话");
        }
    }
    classTeacherextendsPeople{
    publicintage=20;
    publicvoidwork(){
    System.out.println(this.name+"正在教书"+"今年"+this.age);
        }
    }
    publicclassTest {
    publicstaticvoidmain(String[] args) {
    Teacherteacher=newTeacher();
    teacher.name="zhangsan";
    teacher.work();
        }
    }

    image.gif

    此时父类和子类都有age属性代码运行后可以看到使用的是子类的属性。

    image.png

    总结:

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

    就算父类中有private修饰的属性或方法子类也会将它继承下来但是无法访问。

    image.png

    super

    在上面的例子中出现了一个新的关键字super。那么super关键字是干什么的?

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

    classPeople{
    publicStringname;
    publicintage=25;
    publicvoidspeak(){
    System.out.println(this.name+"正在说话");
        }
    }
    classTeacherextendsPeople{
    publicintage=20;
    publicvoidwork(){
    System.out.println(this.name+"正在教书"+"今年"+super.age);
        }
    }
    publicclassTest {
    publicstaticvoidmain(String[] args) {
    Teacherteacher=newTeacher();
    teacher.name="zhangsan";
    teacher.work();
        }
    }

    image.gif

    因为父类和子类都有age属性此时如果想访问父类的属性就可以通过super关键字 ,super+.可以访问父类的属性和方法。(下文会为大家介绍super的第三种使用方法)。

    image.png

    子类的构造方法

    此时如果父类有带参数的构造方法那么系统将会报错。

    image.png

    当父类中加入了含有两个参数构造方法之后代码就会报错。

    接下来就为大家介绍一下super关键字的第三种使用方法:

    super();

    它可以调用父类的构造方法。

    注:它必须放在构造方法的第一行。

    因为实例化对象时有两个比较重要的步骤:

    1. 为对象分配内存;
    2. 调用合适的构造方法。

    上面的代码在我们自己写了有参构造方法之后报错的原因就是子类的构造方法没有调用父类的构造方法。(当我们自己写了构造方法后系统就不会再为我们提供构造方法了,而子类对象构造时,需要先调用父类构造方法,然后再执行子类的构造方法。当我们没有写构造方法时系统会默认调用如下的构造方法:

    image.png

    我们只写了有参构造,所以系统就会因为找不到无参构造而报错,此时就需要我们自己进行调用:

    image.png

    子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整。

    注意:

    1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法;
    2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败;
    3. 在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句;
    4. super(...)只能在子类构造方法中出现一次,并且不能和this同时出现。



    final

    在JAVA中只支持以下几种继承方式:

    • 单继承;
    • 多层继承;
    • 不同类继承同一个类。

    一般我们不希望出现超过三层的继承关系继承层次如果继承层次太多太复杂, 就需要考虑对代码进行重构了。

    那我们应该如何阻止别人不让他们进行继承呢?

    JAVA中提供了final关键可以用来修饰变量、成员方法以及类。

    • 修饰变量或字段,表示常量(即不能修改)
    • 修饰类:表示此类不能被继承
    • 修饰方法:表示该方法不能被重写

    我们只要在不想被继承的类的前面用final修饰就可以了:

    image.png

    继承层次上代码的初始化顺序:

    1. 父类静态
    2. 子类静态
    3. 父类实例
    4. 父类构造
    5. 子类实例
    6. 子类构造


    目录
    相关文章
    |
    2月前
    |
    Java 开发者
    重学Java基础篇—Java类加载顺序深度解析
    本文全面解析Java类的生命周期与加载顺序,涵盖从加载到卸载的七个阶段,并深入探讨初始化阶段的执行规则。通过单类、继承体系的实例分析,明确静态与实例初始化的顺序。同时,列举六种触发初始化的场景及特殊场景处理(如接口初始化)。提供类加载完整流程图与记忆口诀,助于理解复杂初始化逻辑。此外,针对空指针异常等问题提出排查方案,并给出最佳实践建议,帮助开发者优化程序设计、定位BUG及理解框架机制。最后扩展讲解类加载器层次与双亲委派机制,为深入研究奠定基础。
    93 0
    |
    1月前
    |
    Java 数据安全/隐私保护
    Java 类和对象
    本文介绍了Java编程中类和对象的基础知识,作为面向对象编程(OOP)的核心概念。类是对象的蓝图,定义实体类型;对象是具体实例,包含状态和行为。通过示例展示了如何创建表示汽车的类及其实例,并说明了构造函数、字段和方法的作用。同时,文章还探讨了访问修饰符的使用,强调封装的重要性,如通过getter和setter控制字段访问。最后总结了类与对象的关系及其在Java中的应用,并建议进一步学习继承等概念。
    |
    2月前
    |
    缓存 安全 Java
    《从头开始学java,一天一个知识点》之:输入与输出:Scanner与System类
    你是否也经历过这些崩溃瞬间?三天教程连`i++`和`++i`都说不清,面试时`a==b`与`equals()`区别大脑空白,代码总是莫名报NPE。这个系列就是为你打造的Java「速效救心丸」!每天1分钟,地铁通勤、午休间隙即可学习。直击高频考点和实际开发中的“坑位”,拒绝冗长概念,每篇都有可运行代码示例。涵盖输入输出基础、猜数字游戏、企业编码规范、性能优化技巧、隐藏技能等。助你快速掌握Java核心知识,提升编程能力。点赞、收藏、转发,助力更多小伙伴一起成长!
    57 19
    |
    2月前
    |
    存储 监控 安全
    重学Java基础篇—类的生命周期深度解析
    本文全面解析了Java类的生命周期,涵盖加载、验证、准备、解析、初始化、使用及卸载七个关键阶段。通过分阶段执行机制详解(如加载阶段的触发条件与技术实现),结合方法调用机制、内存回收保护等使用阶段特性,以及卸载条件和特殊场景处理,帮助开发者深入理解JVM运作原理。同时,文章探讨了性能优化建议、典型异常处理及新一代JVM特性(如元空间与模块化系统)。总结中强调安全优先、延迟加载与动态扩展的设计思想,并提供开发建议与进阶方向,助力解决性能调优、内存泄漏排查及框架设计等问题。
    76 5
    |
    2月前
    |
    缓存 安全 Java
    《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
    🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
    80 11
    |
    1月前
    |
    存储 安全 Java
    深入理解 Java 中的 instanceof 关键字
    本文深入解析了 Java 中的 `instanceof` 关键字,探讨其在类型判断中的作用。作为二元操作符,`instanceof` 可用于检查对象是否为某类实例或实现特定接口,避免类型转换异常 (`ClassCastException`)。文章通过多态性下的类型判断、安全类型转换、接口实现检测及集合元素类型判定等实际应用场景,展示了 `instanceof` 的强大功能。掌握该关键字可提高代码健壮性,确保运行时类型安全。
    56 0
    |
    1月前
    |
    Java
    java中一个接口A,以及一个实现它的类B,一个A类型的引用对象作为一个方法的参数,这个参数的类型可以是B的类型吗?
    本文探讨了面向对象编程中接口与实现类的关系,以及里氏替换原则(LSP)的应用。通过示例代码展示了如何利用多态性将实现类的对象传递给接口类型的参数,满足LSP的要求。LSP确保子类能无缝替换父类或接口,不改变程序行为。接口定义了行为规范,实现类遵循此规范,从而保证了多态性和代码的可维护性。总结来说,接口与实现类的关系天然符合LSP,体现了多态性的核心思想。
    38 0
    |
    2月前
    |
    安全 IDE Java
    重学Java基础篇—Java Object类常用方法深度解析
    Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
    83 1
    |
    3月前
    |
    缓存 安全 Java
    Volatile关键字与Java原子性的迷宫之旅
    通过合理使用 `volatile`和原子操作,可以在提升程序性能的同时,确保程序的正确性和线程安全性。希望本文能帮助您更好地理解和应用这些并发编程中的关键概念。
    75 21
    |
    2月前
    |
    Java
    课时14:Java数据类型划分(初见String类)
    课时14介绍Java数据类型,重点初见String类。通过三个范例讲解:观察String型变量、"+"操作符的使用问题及转义字符的应用。String不是基本数据类型而是引用类型,但使用方式类似基本类型。课程涵盖字符串连接、数学运算与字符串混合使用时的注意事项以及常用转义字符的用法。