💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# java 中的`super`关键字 > 原文: [https://beginnersbook.com/2014/07/super-keyword-in-java-with-example/](https://beginnersbook.com/2014/07/super-keyword-in-java-with-example/) `super`关键字指的是直接父类的对象。在学习`super`关键字之前,您必须具备 Java 中[继承](https://beginnersbook.com/2013/03/inheritance-in-java/)的知识,以便您能够理解本指南中给出的示例。 ## 使用`super`关键字 1)当父类和子类都具有相同名称的成员时访问父类的数据成员 2)显式调用父类的无参和参数化构造函数 3)访问父类的方法当子类重写该方法时的类。 **现在让我们借助示例**详细讨论它们: ### 1)如何使用`super`关键字访问父类的变量 当子类中的变量已存在于父类中时,为了访问父类的变量,您需要使用`super`关键字。 让我们举一个例子来理解这一点:在下面的程序中,我们在子类中声明了一个数据成员`num`,父类中已经存在同名的成员。如果不使用`super`关键字,则无法访问父类的`num`变量。 。 ```java //Parent class or Superclass or base class class Superclass { int num = 100; } //Child class or subclass or derived class class Subclass extends Superclass { /* The same variable num is declared in the Subclass * which is already present in the Superclass */ int num = 110; void printNumber(){ System.out.println(num); } public static void main(String args[]){ Subclass obj= new Subclass(); obj.printNumber(); } } ``` 输出: ``` 110 ``` **访问父类的`num`变量:** 通过调用这样的变量,如果类(父类和子类)具有相同的变量,我们可以访问父类的变量。 ```java super.variable_name ``` 让我们采用我们在上面看到的相同示例,这次在`print`语句中我们传递`super.num`而不是`num`。 ```java class Superclass { int num = 100; } class Subclass extends Superclass { int num = 110; void printNumber(){ /* Note that instead of writing num we are * writing super.num in the print statement * this refers to the num variable of Superclass */ System.out.println(super.num); } public static void main(String args[]){ Subclass obj= new Subclass(); obj.printNumber(); } } ``` 输出: ``` 100 ``` 正如您通过使用`super.num`所看到的,我们访问了父类的`num`变量。 ### 2)使用`super`关键字来调用父类的构造函数 当我们创建子类的对象时,`new`关键字调用子类的[构造函数](https://beginnersbook.com/2013/03/constructors-in-java/),它隐式调用父类的构造函数。因此,当我们创建子类的对象时执行的顺序是:首先执行父类构造函数,然后执行子类构造函数。这是因为编译器本身添加了`super()`(这会调用父类的无参数构造函数)作为子类构造函数中的第一个语句。 让我们看一个例子来理解我上面解释的内容: ```java class Parentclass { Parentclass(){ System.out.println("Constructor of parent class"); } } class Subclass extends Parentclass { Subclass(){ /* Compile implicitly adds super() here as the * first statement of this constructor. */ System.out.println("Constructor of child class"); } Subclass(int num){ /* Even though it is a parameterized constructor. * The compiler still adds the no-arg super() here */ System.out.println("arg constructor of child class"); } void display(){ System.out.println("Hello!"); } public static void main(String args[]){ /* Creating object using default constructor. This * will invoke child class constructor, which will * invoke parent class constructor */ Subclass obj= new Subclass(); //Calling sub class method obj.display(); /* Creating second object using arg constructor * it will invoke arg constructor of child class which will * invoke no-arg constructor of parent class automatically */ Subclass obj2= new Subclass(10); obj2.display(); } } ``` **输出:** ```java Constructor of parent class Constructor of child class Hello! Constructor of parent class arg constructor of child class Hello! ``` #### 参数化的`super()`调用来调用父类的参数化构造函数 我们可以在子类的构造函数中显式调用`super()`,但它没有任何意义,因为它会是多余的。这就像明确地做一些其他方式隐含的事情。 但是当我们在父类中有一个带有参数的构造函数时,我们可以使用参数化的超类,如`super(100);`从子类的构造函数中调用父类的[参数化构造函数](https://beginnersbook.com/2014/01/parameterized-constructor-in-java-example/)。 让我们看一个例子来理解这个: ```java class Parentclass { //no-arg constructor Parentclass(){ System.out.println("no-arg constructor of parent class"); } //arg or parameterized constructor Parentclass(String str){ System.out.println("parameterized constructor of parent class"); } } class Subclass extends Parentclass { Subclass(){ /* super() must be added to the first statement of constructor * otherwise you will get a compilation error. Another important * point to note is that when we explicitly use super in constructor * the compiler doesn't invoke the parent constructor automatically. */ super("Hahaha"); System.out.println("Constructor of child class"); } void display(){ System.out.println("Hello"); } public static void main(String args[]){ Subclass obj= new Subclass(); obj.display(); } } ``` **输出:** ```java parameterized constructor of parent class Constructor of child class Hello ``` 在这个例子中有几点需要注意: 1)`super()`(或参数化的`super`必须是构造函数中的第一个语句,否则你将得到编译错误:“构造函数调用必须是构造函数中的第一个语句” 2)当我们在构造函数中明确地放置`super`时,java 编译器没有调用父类的默认无参构造函数。 ### 3)如何在方法覆盖的情况下使用`super`关键字 当子类声明父类中已存在的相同方法时,这称为[方法覆盖](https://beginnersbook.com/2014/01/method-overriding-in-java-with-example/)。我们将在本系列的下一个教程中学习方法覆盖。现在您只需要记住这一点:当子类重写父类的方法时,从子类对象调用该方法总是调用该方法的子类版本。但是通过使用这样的`super`关键字:`super.method_name`可以调用父类的方法(被覆盖的方法)。在方法覆盖的情况下,使用这些术语:重写方法:父类的方法重写方法:子类的方法让我们举一个例子来理解这个概念: ```java class Parentclass { //Overridden method void display(){ System.out.println("Parent class method"); } } class Subclass extends Parentclass { //Overriding method void display(){ System.out.println("Child class method"); } void printMsg(){ //This would call Overriding method display(); //This would call Overridden method super.display(); } public static void main(String args[]){ Subclass obj= new Subclass(); obj.printMsg(); } } ``` **输出:** ```java Child class method Parent class method ``` #### 如果子类没有覆盖任何方法怎么办:不需要`super` 当子类没有覆盖父类方法时,我们不需要使用`super`关键字来调用父类方法。这是因为在这种情况下我们只有每个方法的一个版本,子类可以访问父类方法,所以我们可以直接调用父类的方法而不使用`super`。 ```java class Parentclass { void display(){ System.out.println("Parent class method"); } } class Subclass extends Parentclass { void printMsg(){ /* This would call method of parent class, * no need to use super keyword because no other * method with the same name is present in this class */ display(); } public static void main(String args[]){ Subclass obj= new Subclass(); obj.printMsg(); } } ``` **输出:** ```java Parent class method ```