super
是Java中的一个关键字,用于在子类中引用父类(超类)的成员(如方法、构造方法和成员变量)。
一、调用父类的构造方法
1、隐式调用
在Java中,super
关键字的隐式调用主要发生在子类构造方法中。
具体来说,如果子类的构造方法中没有显式地调用父类的构造方法(通过 super()
),Java编译器会自动在子类构造方法的第一条语句插入对父类无参构造方法(super()
) 的调用。这种调用是隐式的,不需要程序员显式编写代码。
public class Super_Sh_Co {
class Parent {
Parent() {
System.out.println("我是父类的无参构造方法");
}
}
class Child extends Parent {
Child() {
//Java编译器会自动此位置插入super();(隐式调用)
System.out.println("我是子类的无参构造方法");
}
}
public static void main(String[] args) {
Super_Sh_Co ssc = new Super_Sh_Co();
Child c = ssc.new Child();
}
}
输出结果为
2、显式调用
super
关键字的显式调用也可以直接调用父类的无参构造方法,但在子类构造方法中,super()
必须是第一条语句(除非调用了本类的其他构造方法),否则会报错。
public class Super_Sh_Co {
class Parent {
Parent() {
System.out.println("我是父类的无参构造方法");
}
}
class Child extends Parent {
Child() {
super(); //显式调用父类的无参构造方法
System.out.println("我是子类的无参构造方法");
}
}
public static void main(String[] args) {
Super_Sh_Co ssc = new Super_Sh_Co();
Child c = ssc.new Child();
}
}
输出结果同上
如果父类没有无参构造方法,子类的构造方法必须显式调用父类的有参构造方法。
public class Super_Sh_Co {
class Parent {
Parent(int a) {
System.out.println("我是父类的有参构造方法");
}
}
class Child extends Parent {
Child() {
super(1); //显式调用父类的有参构造方法
System.out.println("我是子类的无参构造方法");
}
}
public static void main(String[] args) {
Super_Sh_Co ssc = new Super_Sh_Co();
Child c = ssc.new Child();
}
}
输出结果为
注意:子类的构造方法中必须显式或隐式地调用父类的构造方法,这是 Java 语言的语法规则,不能被绕过,如果父类没有无参构造方法,子类必须显式调用父类的有参构造方法,否则程序会报错。
二、调用父类的普通方法(非构造方法)
1、隐式调用
在Java中,如果子类没有显式使用 super
关键字调用父类的非构造方法,Java编译器不会自动插入对父类非构造方法的调用。
public class Super_Sh_Co {
class Parent {
void Mod1() { //父类非构造方法未被子类显式调用,自身也不会被隐式调用
System.out.println("我是父类的非构造方法");
}
}
class Child extends Parent {
void Mod2() {
System.out.println("我是子类的非构造方法");
}
}
public static void main(String[] args) {
Super_Sh_Co ssc = new Super_Sh_Co();
Child c = ssc.new Child();
c.Mod2();
}
}
输出结果为
所以说,普通方法不会被隐式调用,要想在子类中使用父类的普通方法,子类必须进行显式调用。
2、显式调用
如果子类重写了父类的方法,子类方法会覆盖父类方法。在这种情况下,子类可以通过Super关键字显式调用父类的被覆盖方法。
public class Super_Sh_Co {
class Parent {
void Mod(){
System.out.println("父类的非构造方法");
};
}
class Child extends Parent {
void Mod() { //重写了父类的非构造方法
super.Mod(); //显式调用父类被覆盖的Mod方法
System.out.println("重写了父类的非构造方法");
}
}
public static void main(String[] args) {
Super_Sh_Co ssc = new Super_Sh_Co();
Child c = ssc.new Child();
c.Mod();
}
}
输出结果为
如果子类没有重写父类的方法,直接显式调用调用父类的非构造方法时,会自动调用父类的实现。
public class Super_Sh_Co {
class Parent {
void Mod1() {
System.out.println("我是父类的非构造方法");
}
}
class Child extends Parent {
void Mod2() {
super.Mod1();
System.out.println("我是子类的非构造方法");
}
}
public static void main(String[] args) {
Super_Sh_Co ssc = new Super_Sh_Co();
Child c = ssc.new Child();
c.Mod2();
}
}
输出结果为
三、访问父类的成员变量
如果子类和父类有同名的成员变量,可以通过 super
关键字来访问父类的成员变量。
public class Super_Sh_Co {
class Parent {
int x = 10;
}
class Child extends Parent {
int x = 20;
void show() {
System.out.println("子类的实例变量x值为:"+x);
System.out.println("父类的实例变量x值为:"+super.x);
}
}
public static void main(String[] args) {
Super_Sh_Co ssc = new Super_Sh_Co();
Child c = ssc.new Child();
c.show();
}
}
输出结果为
注意事项:
1、super
的使用范围:
(1)
super
只能在子类中使用,不能在父类中使用。
(2)super
不能用于调用父类的静态方法或静态变量,因为静态成员属于类本身,而不是对象。
2、super
和 this
的区别:
(1)this
用于引用当前对象,而 super
用于引用父类对象。
(2)this
用于调用当前类的构造方法或方法,而 super
用于调用父类的构造方法或方法。
3、super
的调用时机:
(1)
在子类的构造方法中,super()
必须是第一条语句(除非调用了本类的其他构造方法)。
(2)
如果父类有无参构造方法,编译器会自动插入 super()
;否则,必须显式调用父类的构造方法。
总结:
1、
子类可以通过 super
调用父类的方法、构造方法和成员变量。
2、super
是子类访问父类成员的重要机制,尤其在方法重写或成员变量隐藏的情况下。
3、super
的使用需要遵循一定的规则,例如不能用于静态成员,且在构造方法中必须是第一条语句。