4.1 继承

实际场景:

如我们有一个Person的类,该类中有姓名、性别、年龄三个属性以及打印信息的方法。

我们还有一个学生类,该类中也是姓名、性别、年龄是三个属性及打印信息的方法

此外,我们还有工人类、教师类等,也是上述属性和方法(或者在上述属性基础上还有别的属性,在上述方法基础上还有别的方法)。

如果Person类、学生类、工人类,教师类等一个个去写,关于姓名、性别、年龄、打印属性的方法这些代码就会重复好几遍,此时可以使用继承(和python)一致。可以先写一个Person类,让学生类、工人类、教师类都继承Person类。Person类称为父类,学生类、供人类、教师类等都称为子类

Java运行结果PersonB 被调用 java的person_Java运行结果PersonB 被调用


如下图,写好一个Person的类

Java运行结果PersonB 被调用 java的person_Java运行结果PersonB 被调用_02


然后让Student类去继承Person

Java运行结果PersonB 被调用 java的person_构造器_03

4.2 单继承和多层继承

java只允许单继承和多层继承。单继承指一个子类只能有一个父类,但是一个父类可以有很多子类。多层继承即子类继承父类,该父类还可以有一个父类,如下图:

Java运行结果PersonB 被调用 java的person_构造器_04


举例如下:

Java运行结果PersonB 被调用 java的person_父类_05

4.3 方法的重写

方法重写就是子类的方法覆盖父类的方法

Java运行结果PersonB 被调用 java的person_Java运行结果PersonB 被调用_06


方法重写时,上方用@override修饰,可以使用alt+/快捷键快速进行方法重写。如图,先alt+/,然后选择红框

Java运行结果PersonB 被调用 java的person_父类_07


结果如下图所示:

Java运行结果PersonB 被调用 java的person_构造器_08


super为调用父类,这里用不到,可以删除。最终可以写成上图中注释处的内容。

在这里注意和方法的重载相区分。

4.4 关键词super

4.4.1 super简介

java中的super和python的super一样,都是调用父类。

Java运行结果PersonB 被调用 java的person_Java运行结果PersonB 被调用_09


Java运行结果PersonB 被调用 java的person_子类_10

4.4.2 调用父类的构造器

  1. 当父类有无参的构造器或者没有写任何构造器时,子类的所有构造器都会默认调用父类的无参构造器(包括父类没写任何构造器时的默认无参构造器)。注意这里句有个默认调用,也就是不写任何东西时,调用父类无参的构造器,当写了某些代码后,就不是调用父类无参构造器了。具体这个代码是什么,下述会讲。
    前提知识回顾:无论是python还是java,对于一个类,初始化时,就相当于执行了构造器函数,python就相当于执行了def __init__()这个函数,假如def __init__()下面写了print(123),那么一旦实例化,就会立刻打印123。java也是一样的,一旦实例化,就会执行构造器下的代码。所以子类的构造器,一方面是创建自身的构造器,另一方面是调用父类的构造器。
    回归正题,假如ManKind是一个父类,并且有一个无参的构造器,下面打印ManKind这个字符串

    现有一个子类Kids,继承自ManKind,当实例化后,下方打印出了mankind这个字符串

    其效果相当于显性调用了父类的无参构造器,如下所示

    回顾一下python

    上图中子类fireMan的构造器中有一个参数name,其实就是子类的构造器调用了父类的构造器。故def __init__(self, name)有两重含义,第一是子类本身的构造器;第二,name参数表明调用了父类的构造器。
  2. 当父类没有空参数的构造器时,子类构造器必须通过this(参数列表)或者super(参数列表)指定调用本类或父类中相应的构造器。
    还是以父类ManKind为例,其只有一个有参的构造器。

    子类的构造器必须显示地指定调用父类的有参构造器,写法如下:

    怎样理解调用本类或父类中相应的构造器中的调用本类呢?难道可以不调用父类?其实不是的。想一想,假如本类中有一个构造器,暂时称为a,又有一个构造器b。那么b调用a会不会报错呢?答案不会。因为b调用了a,而a肯定调用了父类的构造器(无论是不是有参的),所以b调用a,相当于借助a调用了父类的构造器,故子类的构造器无论如何都会调用父类构造器的。有的是直接调用,有的是间接调用(通过本类的其他构造器调用父类的构造器)
  3. 当父类既有无参构造器,又有有参构造器时,子类想要调用有参构造器(不是默认调用无参构造器),可以用2中的this(参数列表)或者super(参数列表)指定调用本类或父类中相应的构造器。
    总结:子类的构造器一定会调用父类构造器的

4.4.3 java中构造器及子类调用情况总结

Java运行结果PersonB 被调用 java的person_父类_11

4.4.4 super和this的区别

Java运行结果PersonB 被调用 java的person_Java运行结果PersonB 被调用_12

4.5 实例化过程

Java运行结果PersonB 被调用 java的person_构造器_13


Java运行结果PersonB 被调用 java的person_父类_14

4.6 多态性

Java运行结果PersonB 被调用 java的person_父类_15


Java运行结果PersonB 被调用 java的person_子类_16


Java运行结果PersonB 被调用 java的person_构造器_17

Java运行结果PersonB 被调用 java的person_父类_18