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关键字的,这个我在通过接口抽象类“创建”对象也有讲解。
关于具体的类的初始化及初始化顺序,可以参考类的初始化顺序详解。
注意点
- 如果你没有显式调用super(),系统会为你自动调用父类的无参构造方法,如果父类没有无参构造方法,就会报错。
- 因为Oject类含有无参构造方法,可以不用显式调用。
- 不管是不是显示地调用,你都要知道存在着一条构造方法的调用长链存在着,这条链一直延申到Oject为止。
- 关于隐藏属性,建议大家不要出现,这样会让代码难以阅读维护。
- 最后,希望大家不要和我一样走那么多弯路了。