原文: https://www.programiz.com/java-programming/super-keyword
在本教程中,我们将借助示例学习 Java 中的super
关键字。
Java 中的super
关键字在子类中用于访问超类成员(属性,构造器和方法)。
在学习super
关键字之前,请确保了解 Java 继承。
super
关键字的用途
- 调用在子类中覆盖的超类的方法。
- 如果超类和子类都具有相同名称的属性,则访问超类的属性(字段)。
- 从子类构造器中显式调用超类无参(默认)或参数化构造器。
让我们了解其中的每种用法。
1.访问超类的被覆盖方法
如果在超类和子类中都定义了相同名称的方法,则子类中的方法将覆盖超类中的方法。 这称为方法覆盖的方法。
示例 1:方法覆盖
class Animal {
// overridden method
public void display(){
System.out.println("I am an animal");
}
}
class Dog extends Animal {
// overriding method
@Override
public void display(){
System.out.println("I am a dog");
}
public void printMessage(){
display();
}
}
class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.printMessage();
}
}
输出
I am a dog
在此示例中,通过使Dog
类的对象dog1
,我们可以调用其方法printMessage()
,该方法然后执行display()
语句。
由于在两个类中都定义了display()
,因此Dog
子类的方法将覆盖Animal
超类的方法。 因此,将调用子类的display()
。
如果必须调用超类的被覆盖方法怎么办?
如果需要调用超类Animal
的覆盖方法display()
,则使用super.display()
。
示例 2:super
调用超类方法
class Animal {
// overridden method
public void display(){
System.out.println("I am an animal");
}
}
class Dog extends Animal {
// overriding method
@Override
public void display(){
System.out.println("I am a dog");
}
public void printMessage(){
// this calls overriding method
display();
// this calls overridden method
super.display();
}
}
class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.printMessage();
}
}
输出:
I am a dog
I am an animal
在这里,上述程序是如何工作的。
2.访问超类的属性
超类和子类可以具有相同名称的属性。 我们使用super
关键字访问超类的属性。
示例 3:访问超类属性
class Animal {
protected String type="animal";
}
class Dog extends Animal {
public String type="mammal";
public void printType() {
System.out.println("I am a " + type);
System.out.println("I am an " + super.type);
}
}
class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.printType();
}
}
输出:
I am a mammal
I am an animal
在此示例中,我们在超类Animal
和子类Dog
中都定义了相同的实例字段type
。
然后,我们创建了Dog
类的对象dog1
。 然后,使用该对象调用printType()
方法。
在printType()
函数内,
type
是子类Dog
的属性。super.type
是超类Animal
的属性。
因此,System.out.println("I am a " + type);
打印I am a mammal
。 而且,System.out.println("I am an " + super.type);
打印I am an animal
。
3.使用super()
访问超类构造器
众所周知,创建类的对象时,将自动调用其默认构造器。
要从子类构造器中显式调用超类构造器,我们使用super()
。 这是super
关键字的一种特殊形式。
super()
仅可在子类构造器中使用,并且必须是第一条语句。
示例 4:使用super()
class Animal {
// default or no-arg constructor of class Animal
Animal() {
System.out.println("I am an animal");
}
}
class Dog extends Animal {
// default or no-arg constructor of class Dog
Dog() {
// calling default constructor of the superclass
super();
System.out.println("I am a dog");
}
}
class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
}
}
输出
I am an animal
I am a dog
在这里,当创建Dog
类的对象dog1
时,它将自动调用该类的默认或无参数构造器。
在子类构造器中,super()
语句调用超类的构造器并在其中执行该语句。 因此,我们得到输出我是动物。
然后,程序流返回到子类构造器,并执行其余的语句。 因此,将打印我是狗。
但是,不是必须使用super()
。 即使在子类构造器中未使用super()
,编译器也会隐式调用超类的默认构造器。
那么,如果编译器自动调用super()
,为什么还要使用冗余代码?
如果必须从子类构造器中调用超类的参数化构造器(带有参数的构造器),则是必需的。
参数化的super()
必须始终是子类的构造器主体中的第一条语句,否则,将出现编译错误。
示例 5:使用super()
调用参数化构造器
class Animal {
// default or no-arg constructor
Animal() {
System.out.println("I am an animal");
}
// parameterized constructor
Animal(String type) {
System.out.println("Type: "+type);
}
}
class Dog extends Animal {
// default constructor
Dog() {
// calling parameterized constructor of the superclass
super("Animal");
System.out.println("I am a dog");
}
}
class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
}
}
输出:
Type: Animal
I am a dog
编译器可以自动调用无参构造器。 但是,它不能调用参数化的构造器。
如果必须调用参数化的构造器,则需要在子类构造器中显式定义它。
请注意,在上面的示例中,我们显式调用了参数化构造器super("Animal")
。 在这种情况下,编译器不会调用超类的默认构造器。