super关键字
Java中的super关键字的核心含义
super 是 Java 关键字,在实例上下文(非静态场景)中作为受限引用指向当前子类实例的父类实例部分,用于访问父类成员;在构造器上下文(子类构造器)中作为构造器调用语句前缀,用于显式触发直接父类的构造器执行,是子类初始化父类实例部分的唯一合法方式。
下面介绍 super 的三种核心用法
调用父类的成员变量
super.变量名
当子类中声明的成员变量与父类中可访问的(非 private)成员变量同名时,子类的该变量会隐藏父类的同名变量。
隐藏的核心表现是:
直接通过子类实例访问该变量名时,默认指向子类自己的变量;
父类的同名变量并未消失,需通过 super.变量名(实例变量)或 父类名.变量名(静态变量)显式访问。
java
class Parent {
String name = "Parent";
}
class Child extends Parent {
String name = "Child";
public void printNames() {
System.out.println("子类name: " + name); // 访问子类自己的name
System.out.println("父类name: " + super.name); // 访问父类的name
}
}
public class Test {
public static void main(String[] args) {
Child child = new Child();
child.printNames();
}
}
输出结果为:
子类name: Child
父类name: Parent
调用父类的成员方法
当子类重写了父类的方法时,子类中默认调用的是重写后的方法,如果需要在子类中调用父类被重写的原方法,可以用 super.方法名(参数)
当子类重写(Override) 了父类的实例方法后,直接通过子类实例调用该方法名,默认执行的是子类重写后的版本,而 super.方法名(参数) 的核心作用是显式绕过子类的重写版本,调用父类原有的方法实现。
只能调用父类中可被子类访问的方法(非private,符合访问修饰符规则);
只能调用直接父类的方法,无法跨级调用祖父类方法(需通过父类的super间接实现);
只能调用父类的实例方法,静态方法不能用super调用(静态方法用父类名.方法名);
父类有多个重载方法时,super调用需匹配参数列表,明确指定调用哪个重载版本;
java
class Parent {
public void sayHello() {
System.out.println("Parent: Hello");
}
}
class Child extends Parent {
@Override
public void sayHello() {
super.sayHello(); // 调用父类的sayHello()
System.out.println("Child: Hello");
}
}
public class Test {
public static void main(String[] args) {
Child child = new Child();
child.sayHello();
}
}
输出结果为:
Parent: Hello
Child: Hello
调用父类的构造函数
Java 的继承体系中,子类对象本质上是父类实例部分与子类扩展部分的组合。创建子类对象时,必须先初始化父类的实例部分,才能保证子类能正常使用父类的功能。super 调用父类构造器的核心作用是显式触发父类构造器的执行,完成父类实例部分的初始化。
super 调用父类构造器的两种形式,且仅能出现在子类构造器中:
super():调用父类的无参构造器(如果省略,编译器会自动加这行);
super(参数列表):调用父类的有参构造器(参数需匹配),适用于父类无无参构造器或需要给父类传递初始化参数。
super 调用父类构造器的关键,违反任何一条都会编译报错:
super()/super(参数列表) 必须是子类构造器的第一条语句;
子类构造器中,super()/super(参数列表) 与this()(调用子类自身其他构造器)只能二选一,且都必须在首行;
如果子类构造器既没写 super()/super(参数列表),也没写this(),编译器会自动在构造器首行插入super(),即调用父类的无参构造方法;
super 只能调用直接父类的构造器,无法跨级调用祖父类构造器(需通过父类构造器间接传递);
子类只能调用父类中可访问的构造器(父类构造器不能是private,否则子类无法访问)。
java
class Parent {
private String name;
// 父类有参构造
public Parent(String name) {
this.name = name;
}
}class Child extends Parent {
private int age;
// 子类构造方法显式调用父类的有参构造
public Child(String name, int age) {
super(name); // 调用父类的构造方法
this.age = age;
}
}