Java零基础快速入门|Super(上)

本篇文章主要内容
super 概述
super 使用在构造方法中
学习目标
掌握super 都可以用在哪里?理解super 在内存方面的存储位置。掌握怎么通过子类的构造方法调用父类的构造方法。super 什么时候可以省略,什么时候不能省略?
知识框架

super 概述
super 和this 可以对比着学习:
this
this 是一个引用,保存内存地址指向自己。
this 出现在实例方法中,谁调用这个实例方法,this 就代表谁,this 代表当前正在执行这个动作的对象。
this 不能出现在静态方法中。
this 大部分情况下可以省略,在方法中区分实例变量和局部变量的时候不能省略。
“this(实际参数列表)”出现在构造方法第一行,通过当前的构造方法去调用本类当中其它的构造方法。
super
严格来说,super 其实并不是一个引用,它只是一个关键字,super 代表了当前对象中从父类继承过来的那部分特征。this 指向一个独立的对象,super 并不是指向某个“独立”的对象,假设张大明是父亲,张小明是儿子,有这样一句话:大家都说张小明的眼睛、鼻子和父亲的很像。那么也就是说儿子继承了父亲的眼睛和鼻子特征,那么眼睛和鼻子肯定最终还是长在儿子的身上。假设this 指向张小明,那么super 就代表张小明身上的眼睛和鼻子。换句话说super 其实是this 的一部分。如下图所示:张大明和张小明其实是两个独立的对象,两个对象内存方面没有联系,super 只是代表张小明对象身上的眼睛和鼻子,因为这个是从父类中继承过来的,在内存方面使用了super 关键字进行了标记, 对于下图来说“this.眼睛”和“super.眼睛”都是访问的同一块内存空间。

super 和this 都可以使用在实例方法当中。
super 不能使用在静态方法当中,因为super 代表了当前对象上的父类型特征, 静态方法中没有this,肯定也是不能使用super 的。
super 也有这种用法:“super(实际参数列表);”,这种用法是通过当前的构造方法调用父类的构造方法。
接下来,我们来测试一下:

编译报错了:

通过以上的测试,可以看出 this 是可以单独使用的引用,但super 无法输出,编译器提示super 要使用必须是“super.xxx”,显然 super 并不指向独立的对象,并不是保存某个对象的内存地址。
再来看另外的一个测试:

编译报错了:

通过以上的测试,可以看出this 和super 都是无法使用在静态方法当中的。
super 使用在构造方法中
super 使用在构造方法中,语法格式为:super(实际参数列表),这行代码和“this(实际参数列表)”都是只允许出现在构造方法第一行(这一点记住就行了),所以这两行代码是无法共 存的。“super(实际参数列表)”这种语法表示子类构造方法执行过程中调用父类的构造方法。我们来看一段代码:



运行结果如下图所示:

我们把上面的代码片段拿过来放在一起看看:
父类的构造方法:

子类的构造方法:

你有没有察觉到子类的构造方法前三行代码和父类构造方法中的代码是一样的?
接下来把子类的构造方法修改一下,然后再运行测试程序:

运行结果如下图所示:

通过以上代码的学习,“super(实际参数列表);”语法表示调用父类的构造方法,代码复用性增强了,另外一方面也是模拟现实世界当中的“要想有儿子,必须先有父亲”的道理。不过这里的“super(实际参数列表)”在调用父类构造方法的时候,从本质上来说并不是创建一个“独立的父类对象”,而是为了完成当前对象的父类型特征的初始化操作。(或者说通过子类的构造方法调用父类的构造方法,是为了让张小明身上长出具有他父亲特点的鼻子和眼睛,鼻子和眼睛初始化完毕之后,具有父亲的特点,但最终还是长在张小明的身上)。
接下来,再来看一段代码:



运行结果如下图所示:

通过以上运行结果可以得出以下的等效代码:



运行结果如下图所示:

通过以上代码的测试我们得出,当一个构造方法第一行没有显示的调用“super(实际参数 列表)”的话,系统默认调用父类的无参数构造方法“super()”。当然前提是“this(实际参数列表)”也没有显示的去调用(因为 super()和this()都只能出现在构造方法第一行,所以不能并存)。我们可以通过以下程序再次测试一下:


编译报错了:

以上程序为什么会编译报错呢?原因是B 类的构造方法第一行默认会调用“super()”,而super()会调用父类 A 的无参数构造方法,但由于父类 A 中提供了有参数构造方法,导致无参数构造方法不存在,从而编译报错了。所以在实际开发中还是建议程序员将无参数构造方法显示的定义出来,这样就可以避免对象的创建失败了。
另外,通过以上内容的学习,还可以得出这样的结论:在 java 语言当中无论是创建哪个Java
对象,老祖宗Object 类中的无参数构造方法是必然执行的。
接下来我们再来看一下:一个 java 对象在创建过程中比较完整的内存图是如何变化的,请先看以下代码:

运行结果如下图所示:

以上程序创建Worker 对象时构造方法的执行顺序是:
先执行Object 类的无参数构造方法;
再执行People 类的构造方法;
最后执行Worker 类的构造方法;
注意:虽然执行了三个构造方法,但是对象实际上只创建了一个Worker。以上程序的内存结构图是这样变化的:

通过以上内容的学习,super()的作用主要是:第一,调用父类的构造方法,使用这个构造方法来给当前子类对象初始化父类型特征;第二,代码复用。
最后附Java零基础视频教程给大家,配合学习效果更佳!!

