咱们已经知道,若是子类中定义的成员变量和父类中的成员变量同名时,则父类中的成员变量不能被继承,此时称子类的成员变量隐藏了父类的成员变量。java
当子类中定义了一个方法,而且这个方法的名字,返回类型,参数个数以及类型和父类的某个方法彻底相同时,父类的这个方法将被隐藏(重写),既不能被子函数
类继承下来。若是咱们在子类中想使用被子类隐藏的父类的成员变量或方法就可使用关键字super。所以,super是用在子类中,目的是访问直接父类中被屏蔽继承
的成员,注意是直接父类(就是类之上最近的超类)。编译器
1 使用super调用父类的构造方法编译
子类不继承父类的构造方法。所以,子类若是想使用父类的构造方法,必须在子类的构造方法中使用,而且必须使用关键字super来表示。并且super必须是变量
子类构造方法中的头一条语句(也就是说父类必须本身负责初始化她本身的状态而不是让子类来作)。构造函数
须要注意的是:若是在子类的构造方法中,没有显示地使用super关键字调用父类的某个构造方法,那么默认地有 super();语句,即调用父类的不带参数的构引用
造方法。若是父类没有提供不带参数的构造方法,就会出现错误。特别注意:当存在有参构造器时,无参构造器就不存在了,必须显示的声明空构造器。方法
2 使用super操做被隐藏的成员变量和方法call
若是咱们在子类中想使用被子类隐藏了的父类的成员变量或方法就可使用关键字super。好比super.x,super.play(),就是被子类隐藏的父类的成员变量x和方法play()。
关键字super和继承一块儿创建类和它的父类的紧密联系。例如,当咱们要调用一个实例方法时,若是实例自己并无定义该方法,那咱们天然地会获得它的父类中定义的同名方法。
尽管会由于方法的覆盖或者使用定义与父类同样的实例或类变量(叫作“隐藏”)而失去这种访问的权力。这就是为何要使用super这个关键字,它显式地指出子类能够直接访问父类中的某些部分,
尽管有时这种访问会由于种种缘由被屏蔽了的方法在其父类中的原始代码。
关键字Super在构造函数的使用中是很是重要的,和方法不一样,构造函数是不被继承的;所以super是访问父类中构造函数的唯一途径。在子类的构造函数 中,
使用super( )和适当的参数表能够触发对父类构造函数的一个调用,若是父类没有相应的构造函数,编译器会报错,这就是每一个实例实现的初始化的过程链。
实例先把本身做为一个Object实例进行初始化,而后从它的直接子类开始按照继承链依次调用构造函数直到最后将与当前类直接相关的内容初始化完毕。
子类的构造函数若是要引用super的话,必须把super放在函数的首位,否则会出现这样的报错:
Checket.java:10: call to super must be first statement in constructor
那么在类中用super调用父类构造函数时,为何调用语句必须是子类的第一条语句?
答案:若是想用super继承父类构造的方法,可是没有放在第一行的话,那么在super以前的语句,确定是为了知足本身想要完成某些行为的语句,可是又用了super继承父类的构造方法。那么之前所作的修改就都回到之前了,就是说又成了父类的构造方法了
下面总结一下super的用法:
第1、在子类构造方法中要调用父类的构造方法,用“super(参数列表)”的方式调用,参数不是必须的。
同时还要注意的一点是:“super(参数列表)”这条语句只能用在子类构造方法体中的第一行。
第2、当子类方法中的局部变量或者子类的成员变量与父类成员变量同名时,也就是子类局部变量覆盖父类成员变量时,
用“super.成员变量名”来引用父类成员变量。固然,若是父类的成员变量没有被覆盖,也能够用“super.成员变量名”来引用父类成员变量,不过这是没必要要的。
第3、当子类的成员方法覆盖了父类的成员方法时,也就是子类和父类有彻底相同的方法定义(但方法体能够不一样),此时,用“super.方法名(参数列表)”的方式访问父类的方法。
第4、super关键字只能用在类体中非静态部分,好比构造函数与成员方法中,若在main函数中调用或静态方法中编译会出错,报Cannot use super in a static context的错误!
注意:父类的属性和方法必须是哪些protected或者public等可让子类访问的属性或者方法。