我们已经知道,如果子类中定义的成员变量和父类中的成员变量同名时,则父类中的成员变量不能被继承,此时称子类的成员变量隐藏了父类的成员变量。
当子类中定义了一个方法,并且这个方法的名字,返回类型,参数个数以及类型和父类的某个方法完全相同时,父类的这个方法将被隐藏(重写),既不能被子
类继承下来。如果我们在子类中想使用被子类隐藏的父类的成员变量或方法就可以使用关键字super。因此,super是用在子类中,目的是访问直接父类中被屏蔽
的成员,注意是直接父类(就是类之上最近的超类)。
1 使用super调用父类的构造方法
子类不继承父类的构造方法。因此,子类如果想使用父类的构造方法,必须在子类的构造方法中使用,并且必须使用关键字super来表示。而且super必须是
子类构造方法中的头一条语句(也就是说父类必须自己负责初始化她自己的状态而不是让子类来做)。
需要注意的是:如果在子类的构造方法中,没有显示地使用super关键字调用父类的某个构造方法,那么默认地有 super();语句,即调用父类的不带参数的构
造方法。如果父类没有提供不带参数的构造方法,就会出现错误。特别注意:当存在有参构造器时,无参构造器就不存在了,必须显示的声明空构造器。
2 使用super操作被隐藏的成员变量和方法
如果我们在子类中想使用被子类隐藏了的父类的成员变量或方法就可以使用关键字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的用法:
第一、在子类构造方法中要调用父类的构造方法,用“super(参数列表)”的方式调用,参数不是必须的。
同时还要注意的一点是:“super(参数列表)”这条语句只能用在子类构造方法体中的第一行。
第二、当子类方法中的局部变量或者子类的成员变量与父类成员变量同名时,也就是子类局部变量覆盖父类成员变量时,
用“super.成员变量名”来引用父类成员变量。当然,如果父类的成员变量没有被覆盖,也可以用“super.成员变量名”来引用父类成员变量,不过这是不必要的。
第三、当子类的成员方法覆盖了父类的成员方法时,也就是子类和父类有完全相同的方法定义(但方法体可以不同),此时,用“super.方法名(参数列表)”的方式访问父类的方法。
第四、super关键字只能用在类体中非静态部分,比如构造函数与成员方法中,若在main函数中调用或静态方法中编译会出错,报Cannot use super in a static context的错误!
注意:父类的属性和方法必须是哪些protected或者public等可以让子类访问的属性或者方法。
原文:http://www.cnblogs.com/zheting/p/7751927.html