相信学过Java语言的小伙伴都熟悉super这个关键字,接下来,我们来研究他的一些基础用法吧。
定义名字为Father的类
public class Father {
public String name;
public int age;
public Father() {}
public Father(String name, int age) {
this.name = name;
this.age = age;
System.out.println("父类构造方法调用了!");
}
public void sayHello() {
System.out.println("你好,我是"+name);
}
}
super关键字可以调用父类构造方法
当父类没有无参构造方法的时候,子类实例化的时候,必须显示调用父类的构造方法。
public class Child extends Father {
public Child(String name, int age) {
// 必须位于第一行。
super(name, age);
System.out.println("子类构造方法执行了");
}
}
实例化Chlid类,结果如下:
父类构造方法调用了!
子类构造方法执行了!
为什么非得放在第一行?
super()之所以存在,是有很重要的原因的!因为子类与父类之间是继承关系,而继承就意味着得到父类中所有的成员变量和方法。既然能够得到父类的这些成员,也就意味着子类可以访问父类的方法和成员变量(当然,得到不意味着就可以任意使用,使用的前提是必须是有相应的访问权限) ,如果子类在使用父类成员的时候,父类内的成员变量没有得到正确的初始化,那么就会发生意想不到的错误,所以问题就出现在了这里,如何保证父类成员是安全的呢? 这就得保证父类得到了正确的初始化,而父类正确的初始化就离不开父类的构造函数,super存在的意义也正是如此。在子类的构造函数,如果没有显式使用super(),并且第一行没有使用this()调用子类其他的构造函数,那么编译器就会自动在第一行补齐super()来调用父类的默认构造函数,如果父类没有默认的构造函数就会报错。
super()在第一行的原因就是: 子类有可能访问了父类的成员变量或者方法,比如在构造函数中使用父类的成员函数或者变量,在代码块中使用了父类的方法等, 所以为保证在子类可以访问父类成员的正确性,所以要先完成对父类的初始化。
super关键字可以调用父类成员方法和成员变量(非私有)
super关键字可以用来访问父类的成员方法或变量,当子类成员变量或方法与父类有相同的名字时也会覆盖父类的成员变量或方法,这个时候要想访问父类的成员变量或方法只能通过super关键字来访问,子类方法中的super.方法名()不需要位于第一行。
public class Child extends Father {
public Child(String name, int age) {
// 必须位于第一行。
super(name, age);
System.out.println("子类构造方法执行了!");
}
public void sayHello() {
super.sayHello();
System.out.println("父亲的年龄:"+super.age);
System.out.println("调用父类的方法,获取了父类的属性!");
}
}
调用子类的sayHello方法结果如下:
你好,我是feige
父亲的年龄:23
调用父类的方法,获取了父类的属性!