由于子类不能继承父类的构造方法,因此,要显式调用父类的构造方法,必须在子类的构造方法体的第一行使用super()方法。该方法会调用父类相应的构造方法来完成子类对象的初始化工作。
在以下情况下需要使用super关键字:
①在类的构造方法中,通过super语句调用该类的父类的构造方法。
②在子类中访问父类中的成员。
1.用super()调用父类构造方法
(1)super()表示调用父类中的构造方法
①子类继承父类,子类的构造方法的第一行,系统会默认加上super(),在调用子类的构造方法时,先调用父类的无参数构造方法。
②如果父类中只有有参数构造方法,那么子类继承父类时会报错,因为子类的构造方法在默认调用父类无参数构造方法时,找不到父类的无参数构造方法。
③如果子类的第一行编写了this(),因为this()也会占用第一行,所以此时就会将super()挤掉,就不会调用父类构造方法。
(2)实例分析
1.子类的构造方法会默认在第一行先调用父类无参数构造方法super()。
public class Main { //测试类
public static void main(String[] args) {
Son s=new Son();
}
}
class Father{ //父类
int id;
public Father(){
System.out.println("调用父类中的构造方法");
}
}
class Son extends Father{ //子类
public Son(){
System.out.println("调用子类构造方法");
}
}
运行结果:
调用父类中的构造方法
调用子类构造方法
说明先调用父类无参数构造方法,再调用子类构造方法。
2.父类中没有无参数构造方法。
public class Father{
int id;
//定义有参数构造方法
public Father(int id){
System.out.println("调用父类中的构造方法");
}
}
说明:子类继承父类,因为父类中没有无参数构造方法,所以子类继承父类时会报错。
3.通过在子类中调用父类有参数构造方法来避免这种错误。
public class Main { //测试类
public static void main(String[] args) {
Son s=new Son();
}
}
class Father{ //父类
int id;
//编写有参数构造方法覆盖无参数构造方法
public Father(int id){
System.out.println("调用父类中的构造方法");
}
}
class Son extends Father{ //定义子类
public Son(){ //在构造方法中调用父类有参数构造方法
super(10);
System.out.println("调用子类构造方法");
}
}
测试结果:
调用父类中的构造方法
调用子类构造方法
4.也可以在构造方法中调用本类中其他构造方法,来挤掉super()调用父类中无参数构造方法。
public class Main { //测试类
public static void main(String[] args) {
Son s=new Son();
}
}
class Father{ //父类
int id;
//有参构造方法
public Father(int id){
System.out.println("调用父类中的构造方法");
}
}
class Son extends Father{ //子类
public Son(){ //无参数构造方法
super(10); //手动编写调用父类有参数构造方法
System.out.println("调用子类构造方法");
}
public Son(int i){ //有参数构造方法
this(); //调用本类其他构造方法,挤掉super()
System.out.println();
}
}
2.用super访问父类字段和方法
使用super访问父类中的成员与this关键字的使用相似,只不过它引用的是子类的父类,基本形式如下:
super. member
其中,member 是父类中的方法或属性名称。这种形式多用于子类的成员名隐藏了父类
中的同名成员的情况。
案例:在Animal 类和Cat 类中分别定义了 public 类型的name 属性和private 类型的 name 属性,并且Cat 类继承Animal 类。那么,我们可以在Cat 类中通过super 关键字来访问父类Animal 中的name 属性,通过his关键字来访问本类中的name属性,如下面的代码:
public class Main {
public static void main(String[] args) {
Animal cat=new Cat("动物","喵星人");
System.out.println(cat);
}
}
class Animal{
public String name; //动物名字
}
class Cat extends Animal{
private String name; //名字
public Cat(String name1,String name2){
super.name=name1; //通过super关键词来访问父类中的name属性
this.name=name2; //通过this关键词来访问本类中的name属性
}
public String toString(){
return "我是"+super.name+",我的名字叫"+this.name;
}
}
运行结果:
我是动物,我的名字叫喵星人
上述代码演示了使用 super实现子类调用父类中同名成员的情况。尽管Cat 类中的属性name 隐藏了 Animal类中的name 属性,但是super允许访问父类中的name属性。另外,super还可以用于调用被子类隐藏的方法。
3.关键词super和this的比较
①this关键字代表本类对象,super关键字代表父类对象。
②使用this.的方式可以访问本类的成员方法和成员变量,使用super.的方式可以访问父类的成员方法和成员变量。
③使用this()的方式在构造方法的第一行表示调用本类的构造方法,使用super()的方式在构造方法的第一行表示调用父类的构造方法。