super关键字误区——新手巨坑

前言

笔者之前一直对super关键字不是很理解,尤其是有说法,super关键字会在子对象里创建一个父对象这种说法,第一次听到时我只是感叹java神奇。
这里写图片描述
但是那时作为新手的我,只能选择相信,但是后来越学就越不相信。


误解

在国内查阅相关super关键字介绍,大多也都是说子对象里有父对象。
但是对于下面这种情况:
我们申明一个抽象父类:
这里写图片描述
再继承这个类,并调用super方法:
这里写图片描述
我们知道抽象类是不会有对象的,那么super产生父类对象这种说法就不攻自破了。

结论:这种一个new产生两个对象的说法是错误的。


答案

抱着国内不行,试试国外的心态,我终于找到了答案:
Google:how to understand the keyword super in java?
我看了跟我同样疑惑的外国大兄弟:
这里写图片描述
解答:
这里写图片描述

然后我又从外国大兄弟评论中,找到了我寻找已久的官方文档解释,结合刚才找到的答案,super的用法总结如下:
1.

If your method overrides one of its superclass’s methods, you can
invoke the overridden method through the use of the keyword super. You
can also use super to refer to a hidden field (although hiding fields
is discouraged)
如果子类重写了父类方法,你可以super关键字调用父类方法。你也可以是使用super来访问父类中被隐藏的属性(所谓被隐藏,是子类属性和父类属性出现重名,即使类型不同也会被隐藏)。

2.

With super(), the superclass no-argument constructor is called. With
super(parameter list), the superclass constructor with a matching
parameter list is called.
通过super()调用父类无参构造方法,super(参数)调用含参构造方法


延申问题

到这里,大家又会疑惑,既然是实例化子类对象时没有实例化父类对象,为什么能访问父类里的属性值能够改变呢?
这里大家要疏通一个概念:
装载一个类,会对该类进行初始化,而构造函数也是负责用来初始化的,之所以我们调用super访问父类的值,就是因为初始化了父类属性,但绝没有生成父类对象。
须知调用构造函数初始化≠实例化一个对象,关于实例化对象一定是看new关键字的,这个我在通过接口抽象类“创建”对象也有讲解。
关于具体的类的初始化及初始化顺序,可以参考类的初始化顺序详解


注意点

  1. 如果你没有显式调用super(),系统会为你自动调用父类的无参构造方法,如果父类没有无参构造方法,就会报错。
  2. 因为Oject类含有无参构造方法,可以不用显式调用。
  3. 不管是不是显示地调用,你都要知道存在着一条构造方法的调用长链存在着,这条链一直延申到Oject为止。
  4. 关于隐藏属性,建议大家不要出现,这样会让代码难以阅读维护。
  5. 最后,希望大家不要和我一样走那么多弯路了。
posted @ 2018-08-23 00:37  顾杰伟  阅读(873)  评论(1编辑  收藏  举报